-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[Staking] Add issuance and budget traits in prep for Budget Split #11513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
1d17819
c3dc7e8
6f2742b
14e3aa9
ddd01ec
e14a388
187aa7f
5075904
4571f1f
946ff6a
bb15c4e
e0b4282
2df7d71
c6bbb0f
a30d654
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| title: Add issuance/budget traits | ||
| doc: | ||
| - audience: Runtime Dev | ||
| description: |- | ||
| Moves `EraPayout` trait from `pallet-staking` and `pallet-staking-async` to `sp-staking`, | ||
| eliminating duplicate definitions. Adds a new `budget` module with stake independent | ||
| traits for issuance computation (`IssuanceCurve`) and budget distribution | ||
| (`BudgetRecipient`, `BudgetRecipientList`). Also adds `StakerRewardCalculator` trait for | ||
| customizing validator incentive weights and staker reward splits. | ||
|
|
||
| No behavior changes. Existing `EraPayout` re-exports from both staking pallets are preserved. | ||
| crates: | ||
| - name: sp-staking | ||
| bump: minor | ||
| - name: pallet-staking | ||
| bump: patch | ||
| - name: pallet-staking-async | ||
| bump: patch | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| // This file is part of Substrate. | ||
|
|
||
| // Copyright (C) Parity Technologies (UK) Ltd. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| //! Traits for inflation issuance and budget distribution. | ||
| //! | ||
| //! These traits define how new tokens are minted and distributed among budget recipients | ||
| //! (e.g. staker rewards, validator incentives). | ||
|
|
||
| use alloc::vec::Vec; | ||
| use sp_runtime::BoundedVec; | ||
|
|
||
| /// Maximum length of a budget key identifier. | ||
| pub const MAX_BUDGET_KEY_LEN: u32 = 32; | ||
|
|
||
| /// Identifier for a budget category in the inflation distribution system. | ||
| /// | ||
| /// Each budget recipient (e.g. staker rewards, validator incentive) is identified | ||
| /// by a unique key. Keys are bounded to [`MAX_BUDGET_KEY_LEN`] bytes. | ||
| pub type BudgetKey = BoundedVec<u8, sp_core::ConstU32<MAX_BUDGET_KEY_LEN>>; | ||
|
|
||
| /// Computes new token issuance for a given time period. | ||
| /// | ||
| /// Unlike [`super::EraPayout`], this trait does not depend on staking state. Issuance is | ||
| /// purely a function of total supply and elapsed time. | ||
| pub trait IssuanceCurve<Balance> { | ||
| /// Compute how much new tokens to mint for the given period. | ||
| fn issue(total_issuance: Balance, elapsed_millis: u64) -> Balance; | ||
| } | ||
|
|
||
| /// A recipient of inflation budget. | ||
| /// | ||
| /// Pallets that want a share of inflation implement this trait, providing a unique key | ||
| /// and a pot account where minted funds are deposited. | ||
| pub trait BudgetRecipient<AccountId> { | ||
| /// Unique identifier for this budget category. | ||
| fn budget_key() -> BudgetKey; | ||
| /// The account that receives minted inflation funds. | ||
| fn pot_account() -> AccountId; | ||
| } | ||
|
|
||
| /// Aggregates multiple [`BudgetRecipient`]s into a list. | ||
| /// | ||
| /// Implemented for tuples of `BudgetRecipient` types, allowing runtime configuration like: | ||
| /// ```ignore | ||
| /// type BudgetRecipients = (StakerRewardRecipient, ValidatorIncentiveRecipient); | ||
| /// ``` | ||
| pub trait BudgetRecipientList<AccountId> { | ||
| /// Collect all registered recipients as `(key, account)` pairs. | ||
| fn recipients() -> Vec<(BudgetKey, AccountId)>; | ||
| } | ||
|
|
||
| impl<AccountId> BudgetRecipientList<AccountId> for () { | ||
| fn recipients() -> Vec<(BudgetKey, AccountId)> { | ||
| Vec::new() | ||
| } | ||
| } | ||
|
|
||
| #[impl_trait_for_tuples::impl_for_tuples(1, 10)] | ||
| #[tuple_types_custom_trait_bound(BudgetRecipient<AccountId>)] | ||
| impl<AccountId> BudgetRecipientList<AccountId> for Tuple { | ||
| fn recipients() -> Vec<(BudgetKey, AccountId)> { | ||
| let mut v = Vec::new(); | ||
| for_tuples!( #( v.push((Tuple::budget_key(), Tuple::pot_account())); )* ); | ||
|
Ank4n marked this conversation as resolved.
|
||
| v | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -32,6 +32,7 @@ use sp_runtime::{ | |||||
| Debug, DispatchError, DispatchResult, Perbill, Saturating, | ||||||
| }; | ||||||
|
|
||||||
| pub mod budget; | ||||||
| pub mod offence; | ||||||
|
|
||||||
| pub mod currency_to_vote; | ||||||
|
|
@@ -726,6 +727,57 @@ pub trait DelegationMigrator { | |||||
| fn force_kill_agent(agent: Agent<Self::AccountId>); | ||||||
| } | ||||||
|
|
||||||
| /// Handler for determining how much of a balance should be paid out on the current era. | ||||||
| /// | ||||||
| /// [`budget::IssuanceCurve`] is the successor to this trait, decoupling issuance computation | ||||||
| /// from staking state. | ||||||
| pub trait EraPayout<Balance> { | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will be deprecated in the following PR |
||||||
| /// Determine the payout for this era. | ||||||
| /// | ||||||
| /// Returns the amount to be paid to stakers in this era, as well as whatever else should be | ||||||
| /// paid out ("the rest"). | ||||||
| fn era_payout( | ||||||
| total_staked: Balance, | ||||||
| total_issuance: Balance, | ||||||
| era_duration_millis: u64, | ||||||
| ) -> (Balance, Balance); | ||||||
| } | ||||||
|
|
||||||
| impl<Balance: Default> EraPayout<Balance> for () { | ||||||
| fn era_payout( | ||||||
| _total_staked: Balance, | ||||||
| _total_issuance: Balance, | ||||||
| _era_duration_millis: u64, | ||||||
| ) -> (Balance, Balance) { | ||||||
| (Default::default(), Default::default()) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// Result of staker reward calculation. | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| pub struct StakerRewardResult<Balance> { | ||||||
| /// Total payout for the validator (staking reward + commission). | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its not self-stake incentive, but the reward based on their self stake from the stakers pot (shared with nominators). |
||||||
| pub validator_payout: Balance, | ||||||
| /// Total payout for all nominators (to be split proportionally by caller). | ||||||
| pub nominator_payout: Balance, | ||||||
| } | ||||||
|
|
||||||
| /// Calculates staking rewards and validator incentive weights. | ||||||
| pub trait StakerRewardCalculator<Balance> { | ||||||
| /// Calculate the reward weight for a validator based on their self-stake. | ||||||
| /// | ||||||
| /// Used for distributing validator self-stake incentive rewards proportionally. | ||||||
| fn calculate_validator_incentive_weight(self_stake: Balance) -> Balance; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without any implementation yet, can you document how these two are meant to be used? I think I figured it out last time by looking at the code, but have forgotten again, and not intuitive enough (= I am not smart enough) to reverse-engineer 🙈 I am not sure what is this weight + how it related to the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. improved the doc, hopefully more now? 946ff6a This trait combines staker reward split and incentive weight calculation. Could argue to split it as well, but a runtime can always create a custom impl that delegates to different strategies internally, so I think this is fine. tldr for incentive weight: every validator gets reward proportional to their_weight / total_weight. |
||||||
|
|
||||||
| /// Calculate how staking rewards are split between validator and nominators. | ||||||
| fn calculate_staker_reward( | ||||||
| validator_total_reward: Balance, | ||||||
| validator_commission: Perbill, | ||||||
| validator_own_stake: Balance, | ||||||
| total_stake: Balance, | ||||||
| ) -> StakerRewardResult<Balance>; | ||||||
| } | ||||||
|
|
||||||
| sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $); | ||||||
| sp_core::generate_feature_enabled_macro!(std_or_benchmarks_enabled, any(feature = "std", feature = "runtime-benchmarks"), $); | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to put
majorhere to make check-semver happier (E.g. https://github.com/paritytech/polkadot-sdk/actions/runs/23793615511/job/69335428077?pr=11513)?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its moved to sp-staking and re-exported from the crates where it was removed. So should not break anything, right? Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you're right but I don't think check-semver is too smart to catch it 😅 Now, it's not a mandatory job to merge, but will require some attention if (hopefully not) it doesn't make the cut for 2604. Do nothing or validate:false might be an option as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't wanna retrigger CI (it takes forever 😂 )
pallet_staking_asyncwill bump to major in the following PRs. But I can keep an eye on this.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
totally fine by me - let's all 🙏 that CI Gods are gentle with us and we can merge now finally 😄