From 9d8dedbd421e323552c330f22e9928e76a0d0335 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Thu, 17 Oct 2024 19:06:03 +0000 Subject: [PATCH 1/3] SIMD-0185: Vote Account v4 --- proposals/0185-vote-account-v4.md | 243 ++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 proposals/0185-vote-account-v4.md diff --git a/proposals/0185-vote-account-v4.md b/proposals/0185-vote-account-v4.md new file mode 100644 index 000000000..0cdeda60a --- /dev/null +++ b/proposals/0185-vote-account-v4.md @@ -0,0 +1,243 @@ +--- +simd: '0185' +title: Vote Account v4 +authors: Justin Starry (Anza) +category: Standard +type: Core +status: Review +created: 2024-10-17 +feature: (fill in with feature tracking issues once accepted) +--- + +## Summary + +A new update for the vote program is proposed to improve authorized voter +bookkeeping as well as allow validators to set commission rates and collector +accounts for different revenue sources. + +## Motivation + +This SIMD details two different modifications to the vote program and vote +account state and combines these changes into one proposal so that only +one vote account version update is needed. + +### Revenue Collection Customization + +- There is only one commission rate stored in vote account state but validators +with to be able to use different commission rates for different income streams +like block rewards and tips. + +- It's not possible to customize which accounts income is collected into. +Currently all block rewards and tips are always collected into the validator +identity account which cannot be a cold wallet since the identity needs to sign +a lot of messages for various network protocols used in Solana like turbine, +gossip, and QUIC. + +### Authorized voter bookkeeping + +- Over 40% of vote state size is reserved for tracking a history of 32 prior +authorized voters for the vote account in the `prior_voters` field. Having such +a long history of prior voters is arguably not very useful, tracking the most +recent previous epoch's voter is probably sufficient and can be stored in the +`authorized_voters` field instead. + +- The `authorized_voters` field doesn't store the voter for the previous epoch +so it's impossible to have a transition epoch where both the previous and newly +assigned voter can both sign votes. + +## Alternatives Considered + +### Reuse vote commission + +Vote accounts already allow validators to set a commission rate for inflation +rewards and so it's not unreasonable to expect that this commission rate could +also be used to distribute block rewards. However, some validators have +expressed a desire to be able to tune revenue streams indpendently. + +## New Terminology + +- Block Fees Collector: The account used to collect commissioned block fees for +validators. Previously collected by default into the validator identity account. + +- Block Tips Collector: The account used to collect commissioned block tips for +validators. Previously configured by a Jito CLI parameter. + +- Inflation Rewards Collector: The account used to collect commissioned +inflation rewards for validators. Previously collected by default into the vote +account. + +- Block Fees Commission: The commission rate that determines how much of block +base fee and priority fee revenue is collected by the validator before +distributing remaining funds to stake delegators. Previously 100% of block fees +were distributed to the validator identity account. + +- Block Tips Commission: The commission rate that determines how much of block +tip revenue is collected by the validator before distributing remaining funds to +stake delegators. Previously configured by a Jito CLI parameter. + +- Inflation Rewards Commission: The commission rate that determines how much of +stake inflation rewards are collected by the validator before distributing the +remaining rewards to stake delegators. Previously referred to as simply the +"commission" since there was no need to differentiate from other types of +commission. + +## Detailed Design + +Currently, all block fees, including both transaction base fees and priority +fees, are collected into a validator's node id account. This proposal details +changes to the Vote Program and Vote Account that will allow validators to +specify how different sources of income are collected. This proposal also +updates the bookkeeping for authorized voters in the vote account state. + +### Vote Account + +A new version of vote state will be introduced with the enum discriminant value +of `3u32` which will be little endian encoded in the first 4 bytes of account +data. + +```rust +pub enum VoteStateVersions { + V1(..), + V2(..), + V3(..), + V4(..), // <- new variant +} +``` + +This new version of vote state will include new fields for setting the +commission and collector account for each of the three sources of validator +income: inflation rewards, block fees, and block tips. It will also remove +the `prior_voters` field. + +```rust +pub struct VoteStateV4 { + pub node_pubkey: Pubkey, + pub authorized_withdrawer: Pubkey, + + /// NEW: the collector accounts for validator income + pub inflation_rewards_collector: Pubkey, + pub block_fees_collector: Pubkey, + pub block_tips_collector: Pubkey, + + /// NEW: percentages (0-100) that represent how much of each income source + /// should be given to this VoteAccount + pub inflation_rewards_commission: u8, + pub block_fees_commission: u8, + pub block_tips_commission: u8, + + /// NEW: bump seed for deriving this vote accounts stake rewards pool address + pub stake_rewards_pool_bump_seed: u8, + + /// REMOVED + /// prior_voters: CircBuf<(Pubkey, Epoch, Epoch)>, + + pub votes: VecDeque, + pub root_slot: Option, + pub authorized_voters: AuthorizedVoters, + pub epoch_credits: Vec<(Epoch, u64, u64)>, + pub last_timestamp: BlockTimestamp, +} +``` + +Whenever a vote account is modified by the vote program in a transaction AND +hasn't been updated to v4 yet, the account state MUST be saved in the new format +with the following default values for the new fields described above: + +```rust +VoteStateV4 { + // .. + + inflation_rewards_collector: vote_state_v3.node_pubkey, + block_fees_collector: vote_state_v3.node_pubkey, + block_tips_collector: vote_state_v3.node_pubkey, + inflation_rewards_commission: vote_state_v3.commission, + block_fees_commission: 100u8, + block_tips_commission: 100u8, + stake_rewards_pool_bump_seed: find_stake_rewards_pool_bump_seed(vote_pubkey), + + // .. +} + +fn find_stake_rewards_pool_bump_seed(vote_pubkey: &Pubkey) -> u8 { + Pubkey::find_program_address( + [ + b"stake_rewards_pool", + vote_pubkey.as_ref(), + ], + &stake_program::id(), + ).1 +} +``` + +### Vote Program + +```rust +pub enum VoteInstruction { + // .. + UpdateCommission {..} // 5u32 + // .. + UpdateCommissionWithKind { // 16u32 + commission: u8, + kind: CollectorKind, + }, + UpdateCollectorAccount { // 17u32 + pubkey: Pubkey, + kind: CollectorKind, + }, +} + +#[repr(u8)] +pub enum CollectorKind { + InflationRewards = 0, + BlockFees, + BlockTips, +} +``` + +#### `UpdateCommission` + +The existing `UpdateCommission` instruction (with enum discriminant `5u32`) will +continue to exist but will continue to only update the inflation rewards +commission. + +#### `UpdateCommissionWithKind` + +A new instruction for setting different kinds of commissions will be added to +the vote program with the enum discriminant of `16u32` little endian encoded in +the first 4 bytes. + +#### `UpdateCollectorAccount` + +A new instruction for setting collector accounts will be added to the vote +program with the enum discriminant value of `17u32` little endian encoded in the +first 4 bytes. + +#### `Authorize`, `AuthorizeChecked`, `AuthorizeWithSeed`, `AuthorizeCheckedWithSeed` + +Existing authorize instructions will be processed differently when setting new +authorized voters. Rather than purging authorized voter entries from the +`authorized_voters` field that correspond to epochs less than the current epoch, +only purge entries less than the previous epoch (current epoch - 1). This will +mean that the `authorized_voters` field can now hold up to 4 entries for the +epochs in the range `[current_epoch - 1, current_epoch + 2]`. Keeping the +authorized voter around from the previous epoch will allow the protocol to +accept votes from both the current and previous authorized voters to make voter +transitions smoother. + +## Impact + +This is a prerequisite for implementing block reward distribution in SIMD-0123. + +## Security Considerations + +What security implications/considerations come with implementing this feature? +Are there any implementation-specific guidance or pitfalls? + +## Drawbacks *(Optional)* + +Why should we not do this? + +## Backwards Compatibility *(Optional)* + +Does the feature introduce any breaking changes? All incompatibilities and +consequences should be listed. \ No newline at end of file From ddc80c248eeb224f39acff1a3154ef5618618d11 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Tue, 5 Nov 2024 16:48:41 +0000 Subject: [PATCH 2/3] remove tips, use bps --- proposals/0185-vote-account-v4.md | 64 +++++++++++++------------------ 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/proposals/0185-vote-account-v4.md b/proposals/0185-vote-account-v4.md index 0cdeda60a..f51343c3f 100644 --- a/proposals/0185-vote-account-v4.md +++ b/proposals/0185-vote-account-v4.md @@ -24,14 +24,13 @@ one vote account version update is needed. ### Revenue Collection Customization - There is only one commission rate stored in vote account state but validators -with to be able to use different commission rates for different income streams -like block rewards and tips. +want to be able to use different commission rates for different income streams +like block rewards. - It's not possible to customize which accounts income is collected into. -Currently all block rewards and tips are always collected into the validator -identity account which cannot be a cold wallet since the identity needs to sign -a lot of messages for various network protocols used in Solana like turbine, -gossip, and QUIC. +Currently all block rewards are collected into the validator identity account +which cannot be a cold wallet since the identity needs to sign a lot of messages +for various network protocols used in Solana like turbine, gossip, and QUIC. ### Authorized voter bookkeeping @@ -56,24 +55,18 @@ expressed a desire to be able to tune revenue streams indpendently. ## New Terminology -- Block Fees Collector: The account used to collect commissioned block fees for -validators. Previously collected by default into the validator identity account. - -- Block Tips Collector: The account used to collect commissioned block tips for -validators. Previously configured by a Jito CLI parameter. +- Block Rewards Collector: The account used to collect commissioned block +rewards for validators. Previously collected by default into the validator +identity account. - Inflation Rewards Collector: The account used to collect commissioned inflation rewards for validators. Previously collected by default into the vote account. -- Block Fees Commission: The commission rate that determines how much of block -base fee and priority fee revenue is collected by the validator before -distributing remaining funds to stake delegators. Previously 100% of block fees -were distributed to the validator identity account. - -- Block Tips Commission: The commission rate that determines how much of block -tip revenue is collected by the validator before distributing remaining funds to -stake delegators. Previously configured by a Jito CLI parameter. +- Block Rewards Commission: The commission rate that determines how much of +block base fee and priority fee revenue is collected by the validator before +distributing remaining funds to stake delegators. Previously 100% of block +rewards were distributed to the validator identity account. - Inflation Rewards Commission: The commission rate that determines how much of stake inflation rewards are collected by the validator before distributing the @@ -105,9 +98,9 @@ pub enum VoteStateVersions { ``` This new version of vote state will include new fields for setting the -commission and collector account for each of the three sources of validator -income: inflation rewards, block fees, and block tips. It will also remove -the `prior_voters` field. +commission and collector account for each of the sources of validator income: +inflation rewards and block rewards. It will also remove the `prior_voters` +field. ```rust pub struct VoteStateV4 { @@ -116,16 +109,14 @@ pub struct VoteStateV4 { /// NEW: the collector accounts for validator income pub inflation_rewards_collector: Pubkey, - pub block_fees_collector: Pubkey, - pub block_tips_collector: Pubkey, + pub block_rewards_collector: Pubkey, - /// NEW: percentages (0-100) that represent how much of each income source - /// should be given to this VoteAccount - pub inflation_rewards_commission: u8, - pub block_fees_commission: u8, - pub block_tips_commission: u8, + /// NEW: basis points (0-10,000) that represent how much of each income + /// source should be given to this VoteAccount + pub inflation_rewards_commission_bps: u16, + pub block_rewards_commission_bps: u16, - /// NEW: bump seed for deriving this vote accounts stake rewards pool address + /// NEW: bump seed for deriving this vote account's stake rewards pool address pub stake_rewards_pool_bump_seed: u8, /// REMOVED @@ -148,11 +139,9 @@ VoteStateV4 { // .. inflation_rewards_collector: vote_state_v3.node_pubkey, - block_fees_collector: vote_state_v3.node_pubkey, - block_tips_collector: vote_state_v3.node_pubkey, - inflation_rewards_commission: vote_state_v3.commission, - block_fees_commission: 100u8, - block_tips_commission: 100u8, + block_rewards_collector: vote_state_v3.node_pubkey, + inflation_rewards_commission_bps: 100u16 * (vote_state_v3.commission as u16), + block_rewards_commission_bps: 10_000u16, stake_rewards_pool_bump_seed: find_stake_rewards_pool_bump_seed(vote_pubkey), // .. @@ -177,7 +166,7 @@ pub enum VoteInstruction { UpdateCommission {..} // 5u32 // .. UpdateCommissionWithKind { // 16u32 - commission: u8, + commission_bps: u16, kind: CollectorKind, }, UpdateCollectorAccount { // 17u32 @@ -189,8 +178,7 @@ pub enum VoteInstruction { #[repr(u8)] pub enum CollectorKind { InflationRewards = 0, - BlockFees, - BlockTips, + BlockRewards, } ``` From 68a231b9ad5c4132ea7e036cc93a1067ed422777 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Fri, 24 Jan 2025 09:31:36 +0000 Subject: [PATCH 3/3] simplify simd --- proposals/0185-vote-account-v4.md | 189 +++++------------------------- 1 file changed, 29 insertions(+), 160 deletions(-) diff --git a/proposals/0185-vote-account-v4.md b/proposals/0185-vote-account-v4.md index f51343c3f..67fa18d38 100644 --- a/proposals/0185-vote-account-v4.md +++ b/proposals/0185-vote-account-v4.md @@ -11,77 +11,30 @@ feature: (fill in with feature tracking issues once accepted) ## Summary -A new update for the vote program is proposed to improve authorized voter -bookkeeping as well as allow validators to set commission rates and collector -accounts for different revenue sources. +A new update for the vote program is proposed to free up state space used for +unnecessary bookkeeping. ## Motivation -This SIMD details two different modifications to the vote program and vote -account state and combines these changes into one proposal so that only -one vote account version update is needed. +Over 40% of vote state size is reserved for tracking a history of 32 prior +authorized voters in the `prior_voters` field. Having such a long history of +prior voters is not useful onchain and for offchain usecases this information +can be fetched via other means. -### Revenue Collection Customization - -- There is only one commission rate stored in vote account state but validators -want to be able to use different commission rates for different income streams -like block rewards. - -- It's not possible to customize which accounts income is collected into. -Currently all block rewards are collected into the validator identity account -which cannot be a cold wallet since the identity needs to sign a lot of messages -for various network protocols used in Solana like turbine, gossip, and QUIC. - -### Authorized voter bookkeeping - -- Over 40% of vote state size is reserved for tracking a history of 32 prior -authorized voters for the vote account in the `prior_voters` field. Having such -a long history of prior voters is arguably not very useful, tracking the most -recent previous epoch's voter is probably sufficient and can be stored in the -`authorized_voters` field instead. - -- The `authorized_voters` field doesn't store the voter for the previous epoch -so it's impossible to have a transition epoch where both the previous and newly -assigned voter can both sign votes. +By removing the `prior_voters` field, the space in vote accounts can be used for +future field additions to vote state without needing to reallocate existing vote +accounts. ## Alternatives Considered -### Reuse vote commission - -Vote accounts already allow validators to set a commission rate for inflation -rewards and so it's not unreasonable to expect that this commission rate could -also be used to distribute block rewards. However, some validators have -expressed a desire to be able to tune revenue streams indpendently. +NA ## New Terminology -- Block Rewards Collector: The account used to collect commissioned block -rewards for validators. Previously collected by default into the validator -identity account. - -- Inflation Rewards Collector: The account used to collect commissioned -inflation rewards for validators. Previously collected by default into the vote -account. - -- Block Rewards Commission: The commission rate that determines how much of -block base fee and priority fee revenue is collected by the validator before -distributing remaining funds to stake delegators. Previously 100% of block -rewards were distributed to the validator identity account. - -- Inflation Rewards Commission: The commission rate that determines how much of -stake inflation rewards are collected by the validator before distributing the -remaining rewards to stake delegators. Previously referred to as simply the -"commission" since there was no need to differentiate from other types of -commission. +NA ## Detailed Design -Currently, all block fees, including both transaction base fees and priority -fees, are collected into a validator's node id account. This proposal details -changes to the Vote Program and Vote Account that will allow validators to -specify how different sources of income are collected. This proposal also -updates the bookkeeping for authorized voters in the vote account state. - ### Vote Account A new version of vote state will be introduced with the enum discriminant value @@ -93,139 +46,55 @@ pub enum VoteStateVersions { V1(..), V2(..), V3(..), - V4(..), // <- new variant + V4(VoteStateV4), // <- new variant } ``` -This new version of vote state will include new fields for setting the -commission and collector account for each of the sources of validator income: -inflation rewards and block rewards. It will also remove the `prior_voters` -field. +This new version of vote state will remove the `prior_voters` field. ```rust pub struct VoteStateV4 { pub node_pubkey: Pubkey, pub authorized_withdrawer: Pubkey, - - /// NEW: the collector accounts for validator income - pub inflation_rewards_collector: Pubkey, - pub block_rewards_collector: Pubkey, - - /// NEW: basis points (0-10,000) that represent how much of each income - /// source should be given to this VoteAccount - pub inflation_rewards_commission_bps: u16, - pub block_rewards_commission_bps: u16, - - /// NEW: bump seed for deriving this vote account's stake rewards pool address - pub stake_rewards_pool_bump_seed: u8, + pub commission: u8, + pub votes: VecDeque, + pub root_slot: Option, + pub authorized_voters: AuthorizedVoters, /// REMOVED /// prior_voters: CircBuf<(Pubkey, Epoch, Epoch)>, - pub votes: VecDeque, - pub root_slot: Option, - pub authorized_voters: AuthorizedVoters, pub epoch_credits: Vec<(Epoch, u64, u64)>, pub last_timestamp: BlockTimestamp, } ``` -Whenever a vote account is modified by the vote program in a transaction AND -hasn't been updated to v4 yet, the account state MUST be saved in the new format -with the following default values for the new fields described above: - -```rust -VoteStateV4 { - // .. - - inflation_rewards_collector: vote_state_v3.node_pubkey, - block_rewards_collector: vote_state_v3.node_pubkey, - inflation_rewards_commission_bps: 100u16 * (vote_state_v3.commission as u16), - block_rewards_commission_bps: 10_000u16, - stake_rewards_pool_bump_seed: find_stake_rewards_pool_bump_seed(vote_pubkey), - - // .. -} - -fn find_stake_rewards_pool_bump_seed(vote_pubkey: &Pubkey) -> u8 { - Pubkey::find_program_address( - [ - b"stake_rewards_pool", - vote_pubkey.as_ref(), - ], - &stake_program::id(), - ).1 -} -``` - ### Vote Program -```rust -pub enum VoteInstruction { - // .. - UpdateCommission {..} // 5u32 - // .. - UpdateCommissionWithKind { // 16u32 - commission_bps: u16, - kind: CollectorKind, - }, - UpdateCollectorAccount { // 17u32 - pubkey: Pubkey, - kind: CollectorKind, - }, -} - -#[repr(u8)] -pub enum CollectorKind { - InflationRewards = 0, - BlockRewards, -} -``` - -#### `UpdateCommission` - -The existing `UpdateCommission` instruction (with enum discriminant `5u32`) will -continue to exist but will continue to only update the inflation rewards -commission. - -#### `UpdateCommissionWithKind` - -A new instruction for setting different kinds of commissions will be added to -the vote program with the enum discriminant of `16u32` little endian encoded in -the first 4 bytes. - -#### `UpdateCollectorAccount` - -A new instruction for setting collector accounts will be added to the vote -program with the enum discriminant value of `17u32` little endian encoded in the -first 4 bytes. +Whenever a vote account is modified by the vote program in a transaction AND +hasn't been updated to v4 yet, the account state MUST be saved in the new +format. New vote accounts should still be allocated with the same size (3762 +bytes) as the prior vote state version to keep extra space for future field +additions. #### `Authorize`, `AuthorizeChecked`, `AuthorizeWithSeed`, `AuthorizeCheckedWithSeed` -Existing authorize instructions will be processed differently when setting new -authorized voters. Rather than purging authorized voter entries from the -`authorized_voters` field that correspond to epochs less than the current epoch, -only purge entries less than the previous epoch (current epoch - 1). This will -mean that the `authorized_voters` field can now hold up to 4 entries for the -epochs in the range `[current_epoch - 1, current_epoch + 2]`. Keeping the -authorized voter around from the previous epoch will allow the protocol to -accept votes from both the current and previous authorized voters to make voter -transitions smoother. +Since `prior_voters` will be removed in the new vote state version, existing +authorize instructions will no longer need to update `prior_voters` when setting +new authorized voters. ## Impact -This is a prerequisite for implementing block reward distribution in SIMD-0123. +This is a prerequisite for implementing custom block fee collection in SIMD-0232. ## Security Considerations -What security implications/considerations come with implementing this feature? -Are there any implementation-specific guidance or pitfalls? +NA ## Drawbacks *(Optional)* -Why should we not do this? +NA ## Backwards Compatibility *(Optional)* -Does the feature introduce any breaking changes? All incompatibilities and -consequences should be listed. \ No newline at end of file +A new feature gate will be added to switch over vote accounts to the new state version.