-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Nikolaos Dymitriadis <[email protected]>
- Loading branch information
1 parent
2f5c26c
commit d0bd897
Showing
5 changed files
with
162 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
[package] | ||
name = "pallet-block-rewards-payouts" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
frame-support = { workspace = true } | ||
frame-system = { workspace = true } | ||
log = { workspace = true } | ||
parity-scale-codec = { workspace = true } | ||
scale-info = { workspace = true } | ||
sp-std = { workspace = true } | ||
sp-block-rewards-payouts = { workspace = true } | ||
pallet-block-production-log = { workspace = true } | ||
|
||
[dev-dependencies] | ||
sp-core = { workspace = true } | ||
sp-io = { workspace = true } | ||
sp-runtime = { workspace = true } | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"frame-support/std", | ||
"frame-system/std", | ||
"log/std", | ||
"parity-scale-codec/std", | ||
"scale-info/std", | ||
"sp-std/std", | ||
"sp-block-rewards-payouts/std", | ||
"pallet-block-production-log/std" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#![cfg_attr(not(feature = "std"), no_std)] | ||
|
||
use frame_support::pallet_prelude::*; | ||
pub use pallet::*; | ||
use sp_block_rewards_payouts::*; | ||
|
||
pub trait ShouldProcessPayout { | ||
/// Should return slot up to which rewards should be paid out or None. | ||
fn should_pay_out(slot: Slot) -> Option<Slot>; | ||
} | ||
|
||
#[frame_support::pallet] | ||
pub mod pallet { | ||
use super::*; | ||
use frame_system::pallet_prelude::*; | ||
use scale_info::prelude::format; | ||
|
||
#[pallet::pallet] | ||
pub struct Pallet<T>(_); | ||
|
||
#[pallet::config] | ||
pub trait Config: frame_system::Config + pallet_block_production_log::Config { | ||
/// Type identifying reward receiver on the Partner Chain | ||
type BeneficiaryId: Member + Parameter + MaxEncodedLen; | ||
|
||
type ShouldProcessPayout: ShouldProcessPayout; | ||
} | ||
|
||
#[pallet::inherent] | ||
impl<T: Config> ProvideInherent for Pallet<T> { | ||
type Call = Call<T>; | ||
type Error = sp_block_rewards_payouts::InherentError; | ||
const INHERENT_IDENTIFIER: InherentIdentifier = | ||
sp_block_rewards_payouts::INHERENT_IDENTIFIER; | ||
|
||
fn create_inherent(data: &InherentData) -> Option<Self::Call> { | ||
let up_to_slot = Self::get_rewards_inherent_data(data)?.up_to_slot; | ||
|
||
Some(Call::note_payout { up_to_slot }) | ||
} | ||
|
||
fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> { | ||
let Some(expected_inherent_data) = Self::get_rewards_inherent_data(data) else { | ||
return Err(Self::Error::InherentRequired); | ||
}; | ||
|
||
let Self::Call::note_payout { up_to_slot } = call else { | ||
unreachable!("There should be no other extrinsic in the pallet") | ||
}; | ||
|
||
if *up_to_slot != expected_inherent_data.up_to_slot { | ||
return Err(Self::Error::IncorrectSlotBoundary); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn is_inherent(call: &Self::Call) -> bool { | ||
matches!(call, Call::note_payout { .. }) | ||
} | ||
|
||
fn is_inherent_required(data: &InherentData) -> Result<Option<Self::Error>, Self::Error> { | ||
if Self::get_rewards_inherent_data(data).is_some() { | ||
Ok(Some(Self::Error::InherentRequired)) | ||
} else { | ||
Ok(None) | ||
} | ||
} | ||
} | ||
|
||
impl<T: Config> Pallet<T> { | ||
fn get_rewards_inherent_data( | ||
data: &InherentData, | ||
) -> Option<BlockProductionPayoutInfo<T::BlockProducerId, T::BeneficiaryId>> { | ||
data.get_data(&Self::INHERENT_IDENTIFIER) | ||
.map_err(|err| { | ||
format!("Reward payout inherent data is present but invalid: {err:?}") | ||
}) | ||
.unwrap() | ||
} | ||
} | ||
|
||
#[pallet::call] | ||
impl<T: Config> Pallet<T> { | ||
#[pallet::call_index(0)] | ||
#[pallet::weight((0, DispatchClass::Mandatory))] | ||
pub fn note_payout(origin: OriginFor<T>, up_to_slot: Slot) -> DispatchResult { | ||
ensure_none(origin)?; | ||
log::info!( | ||
"💸 Processing block production rewards payouts up to slot {}.", | ||
*up_to_slot | ||
); | ||
pallet_block_production_log::Pallet::<T>::drop_prefix(up_to_slot); | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl<T: Config> Pallet<T> { | ||
pub fn should_pay_out(slot: Slot) -> Option<Slot> { | ||
<T as Config>::ShouldProcessPayout::should_pay_out(slot) | ||
} | ||
|
||
pub fn blocks_to_reward( | ||
slot: Slot, | ||
) -> impl Iterator<Item = (Slot, <T as pallet_block_production_log::Config>::BlockProducerId)> | ||
{ | ||
pallet_block_production_log::Pallet::<T>::peek_prefix(slot) | ||
} | ||
} | ||
} |