diff --git a/proposals/0123-block-revenue-distribution.md b/proposals/0123-block-revenue-distribution.md index c72478f4b..2418e881b 100644 --- a/proposals/0123-block-revenue-distribution.md +++ b/proposals/0123-block-revenue-distribution.md @@ -137,46 +137,67 @@ 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. +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]. -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`. +For each vote account, get its total active stake delegation +during the reward epoch `N - 1`. Let this value be `A`. -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. +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`. 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` +or `distributed_rewards` since block revenue will instead be tracked via the +epoch rewards sysvar lamport balance. #### 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, truncating any sub-lamport portion. + +#### Delegator Rewards Distribution -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. +The reward distribution amounts for each stake account can then be used to +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 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. [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 @@ -246,5 +267,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.