diff --git a/src/flamenco/runtime/program/fd_vote_program.c b/src/flamenco/runtime/program/fd_vote_program.c index ac62dca91b..d8f51a8e5a 100644 --- a/src/flamenco/runtime/program/fd_vote_program.c +++ b/src/flamenco/runtime/program/fd_vote_program.c @@ -551,15 +551,17 @@ compute_vote_latency( ulong voted_for_slot, ulong current_slot ) { return (uchar)fd_ulong_min( fd_ulong_sat_sub( current_slot, voted_for_slot ), UCHAR_MAX ); } -// https://github.com/firedancer-io/solana/blob/v1.17.5/sdk/program/src/vote/state/mod.rs#L496 +// https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L673 static ulong -credits_for_vote_at_index( fd_vote_state_t * self, ulong index ) { +credits_for_vote_at_index( fd_vote_state_t * self, ulong index, int timely_vote_credits, int deprecate_unused_legacy_vote_plumbing ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L679 fd_landed_vote_t * landed_vote = deq_fd_landed_vote_t_peek_index( self->votes, index ); ulong latency = landed_vote == NULL ? 0 : landed_vote->latency; // If latency is 0, this means that the Lockout was created and stored from a software version // that did not store vote latencies; in this case, 1 credit is awarded - if( FD_UNLIKELY( latency == 0 ) ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L691 + if( FD_UNLIKELY( latency == 0 || (deprecate_unused_legacy_vote_plumbing && !timely_vote_credits) ) ) { return 1; } @@ -613,22 +615,31 @@ increment_credits( fd_vote_state_t * self, ulong epoch, ulong credits ) { static inline ulong * last_voted_slot( fd_vote_state_t * self ); -// https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/sdk/program/src/vote/state/mod.rs#L423 +// https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L595 static void process_next_vote_slot( fd_vote_state_t * self, ulong next_vote_slot, ulong epoch, - ulong current_slot ) { + ulong current_slot, + int timely_vote_credits, + int deprecate_unused_legacy_vote_plumbing + + ) { ulong * last_voted_slot_ = last_voted_slot( self ); if( FD_UNLIKELY( last_voted_slot_ && next_vote_slot <= *last_voted_slot_ ) ) return; pop_expired_votes( self, next_vote_slot ); - fd_landed_vote_t landed_vote = { .latency = compute_vote_latency( next_vote_slot, current_slot ), + fd_landed_vote_t landed_vote = { .latency = (timely_vote_credits || !deprecate_unused_legacy_vote_plumbing) ? + // https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L615 + compute_vote_latency( next_vote_slot, current_slot ) : + // https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L617 + 0, ( fd_vote_lockout_t ){ .slot = next_vote_slot } }; + // https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L623 if( FD_UNLIKELY( deq_fd_landed_vote_t_cnt( self->votes ) == MAX_LOCKOUT_HISTORY ) ) { - ulong credits = credits_for_vote_at_index( self, 0 ); + ulong credits = credits_for_vote_at_index( self, 0, timely_vote_credits, deprecate_unused_legacy_vote_plumbing); fd_landed_vote_t landed_vote = deq_fd_landed_vote_t_pop_head( self->votes ); self->has_root_slot = 1; self->root_slot = landed_vote.lockout.slot; @@ -636,6 +647,7 @@ process_next_vote_slot( fd_vote_state_t * self, increment_credits( self, epoch, credits ); } + // https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/state/mod.rs#L634 deq_fd_landed_vote_t_push_tail( self->votes, landed_vote ); double_lockouts( self ); } @@ -1152,6 +1164,7 @@ check_slots_are_valid( fd_vote_state_t * vote_state, return 0; } +// https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L565 static int process_new_vote_state( fd_vote_state_t * vote_state, fd_landed_vote_t * new_state, @@ -1164,21 +1177,25 @@ process_new_vote_state( fd_vote_state_t * vote_state, int rc; FD_TEST( !deq_fd_landed_vote_t_empty( new_state ) ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L575 if( FD_UNLIKELY( deq_fd_landed_vote_t_cnt( new_state ) > MAX_LOCKOUT_HISTORY ) ) { ctx->txn_ctx->custom_err = FD_VOTE_ERR_TOO_MANY_VOTES; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; }; - // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/programs/vote/src/vote_state/mod.rs#L559-L569 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L579 if( FD_UNLIKELY( has_new_root && vote_state->has_root_slot ) ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L581 if( FD_UNLIKELY( new_root < vote_state->root_slot ) ) { ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } } else if( FD_UNLIKELY( !has_new_root && vote_state->has_root_slot ) ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L586 ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } else { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L588 /* no-op */ } @@ -1223,23 +1240,30 @@ process_new_vote_state( fd_vote_state_t * vote_state, /* Accumulate credits earned by newly rooted slots. The behavior changes with timely_vote_credits: prior to this feature, there was a bug that counted a new root slot as 1 credit even if it had never been voted on. timely_vote_credits fixes this bug by only awarding - credits for slots actually voted on and finalized. + credits for slots actually voted on and finalized. */ - Source: - https://github.com/firedancer-io/solana/blob/master/programs/vote/src/vote_state/mod.rs#L613 */ + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L635 int timely_vote_credits = FD_FEATURE_ACTIVE( ctx->slot_ctx, timely_vote_credits ); - ulong earned_credits = !timely_vote_credits; + int deprecate_unused_legacy_vote_plumbing = FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_unused_legacy_vote_plumbing ); + + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L641 + ulong earned_credits = timely_vote_credits ? 0 : 1; if( FD_LIKELY( has_new_root ) ) { for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( vote_state->votes ); !deq_fd_landed_vote_t_iter_done( vote_state->votes, iter ); iter = deq_fd_landed_vote_t_iter_next( vote_state->votes, iter ) ) { fd_landed_vote_t * current_vote = deq_fd_landed_vote_t_iter_ele( vote_state->votes, iter ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L647 if( FD_UNLIKELY( current_vote->lockout.slot <= new_root ) ) { // this is safe because we're inside if has_new_root if( FD_LIKELY( timely_vote_credits || ( current_vote->lockout.slot != new_root ) ) ) { earned_credits = fd_ulong_checked_add_expect( - credits_for_vote_at_index( vote_state, current_vote_state_index ), + credits_for_vote_at_index( vote_state, + current_vote_state_index, + timely_vote_credits, + deprecate_unused_legacy_vote_plumbing + ), earned_credits, "`earned_credits` does not overflow" ); } @@ -1254,46 +1278,78 @@ process_new_vote_state( fd_vote_state_t * vote_state, } } + // For any slots newly added to the new vote state, the vote latency of that slot is not provided by the + // vote instruction contents, but instead is computed from the actual latency of the vote + // instruction. This prevents other validators from manipulating their own vote latencies within their vote states + // and forcing the rest of the cluster to accept these possibly fraudulent latency values. If the + // timly_vote_credits feature is not enabled then vote latency is set to 0 for new votes. + // + // For any slot that is in both the new state and the current state, the vote latency of the new state is taken + // from the current state. + // + // Thus vote latencies are set here for any newly vote-on slots when a vote instruction is received. + // They are copied into the new vote state after every vote for already voted-on slots. + // And when voted-on slots are rooted, the vote latencies stored in the vote state of all the rooted slots is used + // to compute credits earned. + // All validators compute the same vote latencies because all process the same vote instruction at the + // same slot, and the only time vote latencies are ever computed is at the time that their slot is first voted on; + // after that, the latencies are retained unaltered until the slot is rooted. + + // All the votes in our current vote state that are missing from the new vote state + // must have been expired by later votes. Check that the lockouts match this assumption. + + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L686 while( current_vote_state_index < deq_fd_landed_vote_t_cnt( vote_state->votes ) && new_vote_state_index < deq_fd_landed_vote_t_cnt( new_state ) ) { fd_landed_vote_t * current_vote = deq_fd_landed_vote_t_peek_index( vote_state->votes, current_vote_state_index ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L690 fd_landed_vote_t * new_vote = deq_fd_landed_vote_t_peek_index( new_state, new_vote_state_index ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L696 if( FD_LIKELY( current_vote->lockout.slot < new_vote->lockout.slot ) ) { ulong last_locked_out_slot = current_vote->lockout.slot + (ulong)pow( INITIAL_LOCKOUT, current_vote->lockout.confirmation_count ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L697 if( last_locked_out_slot >= new_vote->lockout.slot ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L698 ctx->txn_ctx->custom_err = FD_VOTE_ERR_LOCKOUT_CONFLICT; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L700 current_vote_state_index = fd_ulong_checked_add_expect( current_vote_state_index, 1, "`current_vote_state_index` is bounded by " "`MAX_LOCKOUT_HISTORY` when slot is less than proposed" ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L704 } else if( FD_UNLIKELY( current_vote->lockout.slot == new_vote->lockout.slot ) ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L707 if( new_vote->lockout.confirmation_count < current_vote->lockout.confirmation_count ) { ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATION_ROLL_BACK; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L712 new_vote->latency = deq_fd_landed_vote_t_peek_index( vote_state->votes, current_vote_state_index )->latency; + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L714 current_vote_state_index = fd_ulong_checked_add_expect( current_vote_state_index, 1, "`current_vote_state_index` is bounded by " "`MAX_LOCKOUT_HISTORY` when slot is equal to proposed" ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L717 new_vote_state_index = fd_ulong_checked_add_expect( new_vote_state_index, 1, "`new_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` " "when slot is equal to proposed" ); } else { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L722 new_vote_state_index = fd_ulong_checked_add_expect( new_vote_state_index, 1, @@ -1303,25 +1359,30 @@ process_new_vote_state( fd_vote_state_t * vote_state, } // Comment: - // https://github.com/firedancer-io/solana/blob/v1.17.5/programs/vote/src/vote_state/mod.rs#L703-L709 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L736 if( FD_LIKELY( timely_vote_credits ) ) { + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L737 for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state ); !deq_fd_landed_vote_t_iter_done( new_state, iter ); iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) { fd_landed_vote_t * new_vote = deq_fd_landed_vote_t_iter_ele( new_state, iter ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L738 if( FD_UNLIKELY( new_vote->latency == 0 ) ) { // this is unlikely because as validators upgrade, it should converge to the new vote state + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L739 new_vote->latency = compute_vote_latency( new_vote->lockout.slot, current_slot ); } } } // doesn't matter what the value of slot if `is_some = 0` i.e. `Option::None` + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L744 int both_none = !vote_state->has_root_slot && !has_new_root; if( ( !both_none && ( vote_state->has_root_slot != has_new_root || vote_state->root_slot != new_root ) ) ) { increment_credits( vote_state, epoch, earned_credits ); } + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L750 if( FD_LIKELY( timestamp != NULL ) ) { /* new_state asserted nonempty at function beginning */ ulong last_slot = deq_fd_landed_vote_t_peek_tail( new_state )->lockout.slot; @@ -1329,9 +1390,12 @@ process_new_vote_state( fd_vote_state_t * vote_state, if( FD_UNLIKELY( rc ) ) { return rc; } vote_state->last_timestamp.timestamp = *timestamp; } + + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L754 vote_state->has_root_slot = (uchar)has_new_root; vote_state->root_slot = new_root; - // TODO can prob just fd_memcpy + + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L755 deq_fd_landed_vote_t_remove_all( vote_state->votes ); for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state ); !deq_fd_landed_vote_t_iter_done( new_state, iter ); @@ -1339,6 +1403,7 @@ process_new_vote_state( fd_vote_state_t * vote_state, fd_landed_vote_t * landed_vote = deq_fd_landed_vote_t_iter_ele( new_state, iter ); deq_fd_landed_vote_t_push_tail( vote_state->votes, *landed_vote ); } + return FD_EXECUTOR_INSTR_SUCCESS; } @@ -1446,7 +1511,7 @@ is_commission_update_allowed( ulong slot, fd_epoch_schedule_t const * epoch_sche } } -// https://github.com/anza-xyz/agave/blob/master/programs/vote/src/vote_state/mod.rs#L916 +// https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L916 static int update_commission( ulong vote_acct_idx, fd_borrowed_account_t * vote_account, @@ -1462,7 +1527,7 @@ update_commission( ulong vote_acct_idx, fd_vote_state_versioned_t vote_state_versioned; fd_vote_state_t * vote_state = NULL; - // https://github.com/anza-xyz/agave/blob/master/programs/vote/src/vote_state/mod.rs#L927 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L927 int enforce_commission_update_rule = 1; if (FD_FEATURE_ACTIVE( ctx->slot_ctx, allow_commission_decrease_at_any_time )) { rc = get_state( vote_account, scratch_valloc, &vote_state_versioned ); @@ -1473,7 +1538,7 @@ update_commission( ulong vote_acct_idx, enforce_commission_update_rule = commission > vote_state->commission; } - // https://github.com/anza-xyz/agave/blob/master/programs/vote/src/vote_state/mod.rs#L940 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L940 if( FD_LIKELY( enforce_commission_update_rule && FD_FEATURE_ACTIVE( ctx->slot_ctx, commission_updates_only_allowed_in_first_half_of_epoch ) ) ) { if( FD_UNLIKELY( !is_commission_update_allowed( clock->slot, epoch_schedule ) ) ) { @@ -1587,6 +1652,7 @@ withdraw( return 0; } +// https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L760 static int process_vote_unfiltered( fd_vote_state_t * vote_state, ulong * vote_slots, @@ -1594,41 +1660,48 @@ process_vote_unfiltered( fd_vote_state_t * vote_state, fd_slot_hashes_t const * slot_hashes, ulong epoch, ulong current_slot, + int timely_vote_credits, + int deprecate_unused_legacy_vote_plumbing, fd_exec_instr_ctx_t const * ctx ) { int rc; + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L770 rc = check_slots_are_valid( vote_state, vote_slots, &vote->hash, slot_hashes, ctx ); if( FD_UNLIKELY( rc ) ) return rc; for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote_slots ); !deq_ulong_iter_done( vote_slots, iter ); iter = deq_ulong_iter_next( vote_slots, iter ) ) { ulong * ele = deq_ulong_iter_ele( vote_slots, iter ); - process_next_vote_slot( vote_state, *ele, epoch, current_slot ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L772 + process_next_vote_slot( vote_state, *ele, epoch, current_slot, timely_vote_credits, deprecate_unused_legacy_vote_plumbing); } return 0; } +// https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L783 static int process_vote( fd_vote_state_t * vote_state, fd_vote_t const * vote, fd_slot_hashes_t const * slot_hashes, ulong epoch, ulong current_slot, + int timely_vote_credits, + int deprecate_unused_legacy_vote_plumbing, fd_exec_instr_ctx_t const * ctx ) { - // https://github.com/firedancer-io/solana/blob/v1.17/programs/vote/src/vote_state/mod.rs#L742-L744 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L792 if( FD_UNLIKELY( deq_ulong_empty( vote->slots ) ) ) { ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } - // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/programs/vote/src/vote_state/mod.rs#L734 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L795 ulong earliest_slot_in_history = 0; if( FD_UNLIKELY( !deq_fd_slot_hash_t_empty( slot_hashes->hashes ) ) ) { earliest_slot_in_history = deq_fd_slot_hash_t_peek_tail_const( slot_hashes->hashes )->slot; } - // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/programs/vote/src/vote_state/mod.rs#L735-L740 ulong vote_slots_cnt = deq_ulong_cnt( vote->slots ); uchar * vote_slots_mem = fd_scratch_alloc( deq_ulong_align(), deq_ulong_footprint( vote_slots_cnt ) ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L796 ulong * vote_slots = deq_ulong_join( deq_ulong_new( vote_slots_mem, vote_slots_cnt ) ); for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots ); !deq_ulong_iter_done( vote->slots, iter ); @@ -1639,15 +1712,16 @@ process_vote( fd_vote_state_t * vote_state, } } - // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/programs/vote/src/vote_state/mod.rs#L741-L743 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L802 if( FD_UNLIKELY( deq_ulong_cnt( vote_slots ) == 0 ) ) { ctx->txn_ctx->custom_err = FD_VOTE_ERR_VOTES_TOO_OLD_ALL_FILTERED; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } - // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/programs/vote/src/vote_state/mod.rs#L744 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L805 return process_vote_unfiltered( - vote_state, vote_slots, vote, slot_hashes, epoch, current_slot, ctx ); + vote_state, vote_slots, vote, slot_hashes, epoch, current_slot, + timely_vote_credits, deprecate_unused_legacy_vote_plumbing, ctx ); } static int @@ -1720,6 +1794,7 @@ verify_and_get_vote_state( fd_borrowed_account_t * vote_account, return FD_EXECUTOR_INSTR_SUCCESS; } +// https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1104 static int process_vote_with_account( ulong vote_acct_idx, fd_borrowed_account_t * vote_account, @@ -1731,13 +1806,19 @@ process_vote_with_account( ulong vote_acct_idx, int rc; fd_vote_state_t vote_state; + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1112 rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state ); if( FD_UNLIKELY( rc ) ) return rc; - rc = process_vote( &vote_state, vote, slot_hashes, clock->epoch, clock->slot, ctx ); + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1114 + int timely_vote_credits = FD_FEATURE_ACTIVE( ctx->slot_ctx, timely_vote_credits ); + int deprecate_unused_legacy_vote_plumbing = FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_unused_legacy_vote_plumbing ); + + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1117 + rc = process_vote( &vote_state, vote, slot_hashes, clock->epoch, clock->slot, timely_vote_credits, deprecate_unused_legacy_vote_plumbing, ctx ); if( FD_UNLIKELY( rc ) ) return rc; - // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/programs/vote/src/vote_state/mod.rs#L1007-L1013 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1126 if( FD_LIKELY( vote->timestamp ) ) { if( FD_UNLIKELY( deq_ulong_cnt( vote->slots ) == 0 ) ) { ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; @@ -1745,6 +1826,7 @@ process_vote_with_account( ulong vote_acct_idx, } ulong * max = deq_ulong_peek_head( vote->slots ) ? deq_ulong_peek_head( vote->slots ) : NULL; + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1127 for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots ); !deq_ulong_iter_done( vote->slots, iter ); iter = deq_ulong_iter_next( vote->slots, iter ) ) { @@ -1755,11 +1837,12 @@ process_vote_with_account( ulong vote_acct_idx, ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS; return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; } - // https://github.com/firedancer-io/solana/blob/debug-master/programs/vote/src/vote_state/mod.rs#L1012 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1131 rc = process_timestamp( &vote_state, *max, *vote->timestamp, ctx ); if( FD_UNLIKELY( rc ) ) return rc; } + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_state/mod.rs#L1133 return set_vote_account_state( vote_acct_idx, vote_account, &vote_state, ctx ); } @@ -2414,7 +2497,7 @@ fd_vote_program_execute( fd_exec_instr_ctx_t ctx ) { if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR; - // https://github.com/anza-xyz/agave/blob/master/programs/vote/src/vote_processor.rs#L145 + // https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_processor.rs#L145 rc = update_commission( 0, me, instruction.inner.update_commission, signers, epoch_schedule, clock, &ctx ); break; @@ -2584,10 +2667,10 @@ fd_vote_program_execute( fd_exec_instr_ctx_t ctx ) { /* TowerSync(Switch) * * Instruction: - * https://github.com/anza-xyz/agave/blob/master/sdk/program/src/vote/instruction.rs#L151-L157 + * https://github.com/anza-xyz/agave/blob/v2.0.0/sdk/program/src/vote/instruction.rs#L151-L157 * * Processor: - * https://github.com/anza-xyz/agave/blob/master/programs/vote/src/vote_processor.rs#L196-L215 + * https://github.com/anza-xyz/agave/blob/v2.0.0/programs/vote/src/vote_processor.rs#L196-L215 */ case fd_vote_instruction_enum_tower_sync: