From 6c6cda116abab9170cc883745d52cb80e75affef Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Mon, 9 Jun 2025 22:12:36 +0000 Subject: [PATCH 1/5] amend simd-0123 --- proposals/0123-block-revenue-distribution.md | 64 ++++++++++---------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/proposals/0123-block-revenue-distribution.md b/proposals/0123-block-revenue-distribution.md index c72478f4b..cd3a43b18 100644 --- a/proposals/0123-block-revenue-distribution.md +++ b/proposals/0123-block-revenue-distribution.md @@ -137,43 +137,45 @@ vote state field `pending_delegator_rewards` and added to the balance of vote account. If either of these conditions is violated, the delegator rewards amount MUST be burned. -### Runtime: Delegator Rewards Distribution +### Runtime: Block Revenue Distribution -When calculating stake delegation rewards for a particular completed reward -epoch, construct a list of all vote accounts that were initialized at the -beginning of the reward epoch and had a non-zero active stake delegation. For -each vote account, retrieve its state at the end of the reward epoch and check -the `pending_delegator_rewards` field in its vote state. Let this value be `P`. -If `P` is non-zero, use it to calculate rewards for each of the stake accounts -delegated to the vote account as follows: +At the beginning of each epoch, pending delegator rewards will be collected from +actively staked vote accounts into the epoch rewards sysvar account and then +distributed to stake accounts utilizing the existing partitioned rewards +distribution mechanism described in [SIMD-0118]. -1. Sum all active stake delegated to the vote account during the reward epoch -epoch. Let this total be `A`. +#### Delegator Rewards Calculation -2. For each individual stake account, multiply its active stake from the -reward epoch by `P`, and divide the result by `A` using integer division. -Discard any fractional lamports. +During the beginning of the first block of an epoch `N`, all pending delegator +rewards from all vote accounts with a non-zero active stake delegation during +the reward epoch `N - 1` MUST be transferred by the runtime to the epoch rewards +sysvar account for distribution. -After calculating all individual stake rewards, sum them to obtain `D`, the -total distribution amount. Because of integer division, the full amount `P` may -not be distributed so compute the amount to be burned, `B`, as the difference -between `P` and `D`. - -If no blocks in the epoch following the completed reward epoch have been -processed yet, subtract `B` from both the vote account’s lamport balance and its -`pending_delegator_rewards` field and store the updated vote account. Finally, -the burn amount `B` should also be deducted from the cluster capitalization. +For each actively staked vote account, retrieve its state at the end of the +reward epoch and check the `pending_delegator_rewards` field in its vote state. +Let this value be `P`. If `P` is non-zero, set the `pending_delegator_rewards` +field to `0` and deduct `P` from the vote account's lamport balance and credit +it to the epoch rewards sysvar account's lamport balance. Then if `P` is +non-zero, sum all active stake delegated to the vote account during the reward +epoch epoch `N - 1`. Let this total be `A`. #### Individual Delegator Reward -The stake reward distribution amounts for each stake account calculated above -can then be used to construct a list of stake reward entries which MUST be -partitioned and distributed according to [SIMD-0118]. +For each individual stake account with an active non-zero delegation, multiply +its active stake in reward epoch `N - 1` by `P`, and divide the result by +`A` using integer division to get the individual stake account's block revenue +reward distribution amount. + +#### Delegator Rewards Distribution + +The reward distribution amounts for each stake account can then be used to +construct a list of stake reward entries which MUST be partitioned and +distributed according to [SIMD-0118]. -When reward entries are used to distribute rewards pool funds during partitioned -rewards distribution, the delegated vote account for each rewarded stake account -must have its `pending_delegator_rewards` field and its balance deducted with -the amount of rewards distributed to keep capitalization consistent. +During partitioned reward distribution in a given slot, when reward entries are +used to distribute block revenue rewards, the epoch rewards sysvar account's +lamport balance MUST be debited by the block revenue reward distribution amount +to keep capitalization consistent. [SIMD-0118]: https://github.com/solana-foundation/solana-improvement-documents/pull/118 @@ -246,5 +248,5 @@ NA ## Backwards Compatibility -A feature gate will be used to enable block reward distribution at an epoch -boundary. +A feature gate will be used to enable block revenue reward distribution at an +epoch boundary. From 10e6cc201b76e7ff51551e0dc966d36fc02980ae Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Fri, 8 Aug 2025 06:17:02 +0000 Subject: [PATCH 2/5] clarify burning excess rewards --- proposals/0123-block-revenue-distribution.md | 40 ++++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/proposals/0123-block-revenue-distribution.md b/proposals/0123-block-revenue-distribution.md index cd3a43b18..8c0ae272a 100644 --- a/proposals/0123-block-revenue-distribution.md +++ b/proposals/0123-block-revenue-distribution.md @@ -146,18 +146,29 @@ distribution mechanism described in [SIMD-0118]. #### Delegator Rewards Calculation -During the beginning of the first block of an epoch `N`, all pending delegator -rewards from all vote accounts with a non-zero active stake delegation during -the reward epoch `N - 1` MUST be transferred by the runtime to the epoch rewards -sysvar account for distribution. - -For each actively staked vote account, retrieve its state at the end of the -reward epoch and check the `pending_delegator_rewards` field in its vote state. -Let this value be `P`. If `P` is non-zero, set the `pending_delegator_rewards` -field to `0` and deduct `P` from the vote account's lamport balance and credit -it to the epoch rewards sysvar account's lamport balance. Then if `P` is -non-zero, sum all active stake delegated to the vote account during the reward -epoch epoch `N - 1`. Let this total be `A`. +Delegator rewards MUST be calculated during both the beginning of the first +block of an epoch `N` and after restarting during partitioned rewards +distribution. + +For each vote account, get its total active stake delegation +during the reward epoch `N - 1`. Let this value be `A`. If `A` is zero, skip +this vote account (any pending delegator rewards will be distributed in a future +epoch when the vote account has active stake.) + +Then for each vote account, get its pending delegator rewards from the +`pending_delegator_rewards` field in the vote state at the end of reward epoch +`N - 1`. Let this value be `P`. If `P` is zero, skip this vote account as there +is nothing to be distributed. + +Lastly, if this is the first block of epoch `N`, the vote state's +`pending_delegator_rewards` field MUST be reset to `0` and `P` lamports MUST be +deducted from the vote account's lamport balance and credited to the epoch +rewards sysvar account's lamport balance. + +Note that unlike inflation rewards distribution, block revenue distribution will +not impact any internal epoch rewards sysvar state fields like `total_rewards` +or `distributed_rewards` since block revenue will instead be tracked via the +epoch rewards sysvar lamport balance. #### Individual Delegator Reward @@ -179,6 +190,11 @@ to keep capitalization consistent. [SIMD-0118]: https://github.com/solana-foundation/solana-improvement-documents/pull/118 +#### Delegator Rewards Completion + +After distributing all partitioned delegator rewards, the epoch rewards sysvar balance +MUST be reset to its rent exemption balance and any surplus lamports are burned. + ### Vote Program #### Withdraw From e497e0695e19d509aaf2269a725ddee5c4d510c4 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Mon, 25 Aug 2025 04:06:39 +0000 Subject: [PATCH 3/5] feedback --- proposals/0123-block-revenue-distribution.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/proposals/0123-block-revenue-distribution.md b/proposals/0123-block-revenue-distribution.md index 8c0ae272a..f4a6d4e29 100644 --- a/proposals/0123-block-revenue-distribution.md +++ b/proposals/0123-block-revenue-distribution.md @@ -147,8 +147,8 @@ distribution mechanism described in [SIMD-0118]. #### Delegator Rewards Calculation Delegator rewards MUST be calculated during both the beginning of the first -block of an epoch `N` and after restarting during partitioned rewards -distribution. +block of an epoch `N` and any time the node is restarted during the partitioned +rewards distribution period. For each vote account, get its total active stake delegation during the reward epoch `N - 1`. Let this value be `A`. If `A` is zero, skip @@ -163,7 +163,8 @@ is nothing to be distributed. Lastly, if this is the first block of epoch `N`, the vote state's `pending_delegator_rewards` field MUST be reset to `0` and `P` lamports MUST be deducted from the vote account's lamport balance and credited to the epoch -rewards sysvar account's lamport balance. +rewards sysvar account's lamport balance before any transactions or votes are +processed. Note that unlike inflation rewards distribution, block revenue distribution will not impact any internal epoch rewards sysvar state fields like `total_rewards` @@ -175,7 +176,7 @@ epoch rewards sysvar lamport balance. For each individual stake account with an active non-zero delegation, multiply its active stake in reward epoch `N - 1` by `P`, and divide the result by `A` using integer division to get the individual stake account's block revenue -reward distribution amount. +reward distribution amount, truncating any sub-lamport portion. #### Delegator Rewards Distribution From dbc39ce766dcdf0cd84e77715a15d01b12b60ca5 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Tue, 26 Aug 2025 01:23:55 +0000 Subject: [PATCH 4/5] give rewards to voter if no active stake --- proposals/0123-block-revenue-distribution.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proposals/0123-block-revenue-distribution.md b/proposals/0123-block-revenue-distribution.md index f4a6d4e29..c55e5365e 100644 --- a/proposals/0123-block-revenue-distribution.md +++ b/proposals/0123-block-revenue-distribution.md @@ -151,9 +151,7 @@ block of an epoch `N` and any time the node is restarted during the partitioned rewards distribution period. For each vote account, get its total active stake delegation -during the reward epoch `N - 1`. Let this value be `A`. If `A` is zero, skip -this vote account (any pending delegator rewards will be distributed in a future -epoch when the vote account has active stake.) +during the reward epoch `N - 1`. Let this value be `A`. Then for each vote account, get its pending delegator rewards from the `pending_delegator_rewards` field in the vote state at the end of reward epoch @@ -161,10 +159,12 @@ Then for each vote account, get its pending delegator rewards from the is nothing to be distributed. Lastly, if this is the first block of epoch `N`, the vote state's -`pending_delegator_rewards` field MUST be reset to `0` and `P` lamports MUST be -deducted from the vote account's lamport balance and credited to the epoch -rewards sysvar account's lamport balance before any transactions or votes are -processed. +`pending_delegator_rewards` field MUST be reset to `0`. Then, if `A` (active +stake) is zero, the delegator rewards will effectively returned to the voter +after the `pending_delegator_rewards` field is reset to `0`. Otherwise, if `A` +is non-zero, `P` lamports MUST be debited from the vote account's lamport +balance and credited to the epoch rewards sysvar account's lamport balance +before any transactions or votes are processed. Note that unlike inflation rewards distribution, block revenue distribution will not impact any internal epoch rewards sysvar state fields like `total_rewards` From ae7456744a45107ecbf8f0cc7812e7065aef9c78 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Wed, 3 Sep 2025 02:19:35 +0000 Subject: [PATCH 5/5] more explicit --- proposals/0123-block-revenue-distribution.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/proposals/0123-block-revenue-distribution.md b/proposals/0123-block-revenue-distribution.md index c55e5365e..fbf7603aa 100644 --- a/proposals/0123-block-revenue-distribution.md +++ b/proposals/0123-block-revenue-distribution.md @@ -146,9 +146,10 @@ distribution mechanism described in [SIMD-0118]. #### Delegator Rewards Calculation -Delegator rewards MUST be calculated during both the beginning of the first -block of an epoch `N` and any time the node is restarted during the partitioned -rewards distribution period. +Delegator rewards MUST be calculated during the beginning of the first block of +an epoch `N` where the first block is any block with a parent in the previous +epoch. Rewards MUST be recalculated if a node is restarted during the partitioned +rewards distribution period as described in [SIMD-0118]. For each vote account, get its total active stake delegation during the reward epoch `N - 1`. Let this value be `A`. @@ -181,10 +182,11 @@ reward distribution amount, truncating any sub-lamport portion. #### Delegator Rewards Distribution The reward distribution amounts for each stake account can then be used to -construct a list of stake reward entries which MUST be partitioned and -distributed according to [SIMD-0118]. +construct a list of stake reward entries which MUST be partitioned according to +[SIMD-0118] which describes which stake rewards are distributed in each block +during the partitioned rewards distribution period. -During partitioned reward distribution in a given slot, when reward entries are +During partitioned reward distribution for a given slot, when reward entries are used to distribute block revenue rewards, the epoch rewards sysvar account's lamport balance MUST be debited by the block revenue reward distribution amount to keep capitalization consistent.