Skip to content

Commit

Permalink
flamenco: use new_rate_activation_epoch properly in epoch calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
mjain-jump committed Dec 5, 2024
1 parent c9a7843 commit 4a8027f
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 28 deletions.
35 changes: 27 additions & 8 deletions src/flamenco/rewards/fd_rewards.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ slot_in_year_for_inflation( fd_exec_slot_ctx_t * slot_ctx ) {
https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/programs/stake/src/points.rs#L109 */
static void
calculate_stake_points_and_credits (
calculate_stake_points_and_credits(
fd_stake_history_t const * stake_history,
fd_stake_t * stake,
fd_vote_state_versioned_t * vote_state_versioned,
ulong * new_rate_activation_epoch,
fd_calculated_stake_points_t * result
) {

Expand Down Expand Up @@ -173,7 +174,7 @@ calculate_stake_points_and_credits (

new_credits_observed = fd_ulong_max( new_credits_observed, final_epoch_credits );

ulong stake_amount = fd_stake_activating_and_deactivating( &stake->delegation, ele->epoch, stake_history, NULL ).effective;
ulong stake_amount = fd_stake_activating_and_deactivating( &stake->delegation, ele->epoch, stake_history, new_rate_activation_epoch ).effective;

points += (uint128)stake_amount * earned_credits;
}
Expand All @@ -191,10 +192,11 @@ calculate_stake_rewards(
fd_vote_state_versioned_t * vote_state_versioned,
ulong rewarded_epoch,
fd_point_value_t * point_value,
ulong * new_rate_activation_epoch,
fd_calculated_stake_rewards_t * result
) {
fd_calculated_stake_points_t stake_points_result = {0};
calculate_stake_points_and_credits( stake_history, &stake_state->inner.stake.stake, vote_state_versioned, &stake_points_result);
calculate_stake_points_and_credits( stake_history, &stake_state->inner.stake.stake, vote_state_versioned, new_rate_activation_epoch, &stake_points_result);

// Drive credits_observed forward unconditionally when rewards are disabled
// or when this is the stake's activation epoch
Expand Down Expand Up @@ -238,9 +240,10 @@ redeem_rewards( fd_stake_history_t const * stake_history,
fd_vote_state_versioned_t * vote_state_versioned,
ulong rewarded_epoch,
fd_point_value_t * point_value,
ulong * new_rate_activation_epoch,
fd_calculated_stake_rewards_t * calculated_stake_rewards) {

int rc = calculate_stake_rewards( stake_history, stake_state, vote_state_versioned, rewarded_epoch, point_value, calculated_stake_rewards );
int rc = calculate_stake_rewards( stake_history, stake_state, vote_state_versioned, rewarded_epoch, point_value, new_rate_activation_epoch, calculated_stake_rewards );
if ( FD_UNLIKELY( rc != 0 ) ) {
return rc;
}
Expand All @@ -254,14 +257,15 @@ calculate_points(
fd_stake_state_v2_t * stake_state,
fd_vote_state_versioned_t * vote_state_versioned,
fd_stake_history_t const * stake_history,
ulong * new_rate_activation_epoch,
uint128 * result
) {
if ( FD_UNLIKELY( !fd_stake_state_v2_is_stake( stake_state ) ) ) {
return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
}

fd_calculated_stake_points_t stake_point_result;
calculate_stake_points_and_credits( stake_history, &stake_state->inner.stake.stake, vote_state_versioned, &stake_point_result );
calculate_stake_points_and_credits( stake_history, &stake_state->inner.stake.stake, vote_state_versioned, new_rate_activation_epoch, &stake_point_result );
*result = stake_point_result.points;

return FD_EXECUTOR_INSTR_SUCCESS;
Expand Down Expand Up @@ -341,6 +345,13 @@ calculate_reward_points_partitioned(
ulong minimum_stake_delegation = get_minimum_stake_delegation( slot_ctx );

/* Calculate the points for each stake delegation */
int _err[1];
ulong * new_warmup_cooldown_rate_epoch = fd_scratch_alloc( alignof(ulong), sizeof(ulong) );
int is_some = fd_new_warmup_cooldown_rate_epoch( slot_ctx, new_warmup_cooldown_rate_epoch, _err );
if( FD_UNLIKELY( !is_some ) ) {
new_warmup_cooldown_rate_epoch = NULL;
}

for( fd_delegation_pair_t_mapnode_t const * n = fd_delegation_pair_t_map_minimum_const( epoch_bank->stakes.stake_delegations_pool, epoch_bank->stakes.stake_delegations_root );
n;
n = fd_delegation_pair_t_map_successor_const( epoch_bank->stakes.stake_delegations_pool, n )
Expand Down Expand Up @@ -413,7 +424,7 @@ calculate_reward_points_partitioned(
}

uint128 account_points;
err = calculate_points( stake_state, vote_state, stake_history, &account_points );
err = calculate_points( stake_state, vote_state, stake_history, new_warmup_cooldown_rate_epoch, &account_points );
if ( FD_UNLIKELY( err ) ) {
FD_LOG_DEBUG(( "failed to calculate points" ));
continue;
Expand Down Expand Up @@ -497,7 +508,7 @@ calculate_reward_points_partitioned(
}

uint128 account_points;
err = calculate_points( stake_state, vote_state, stake_history, &account_points );
err = calculate_points( stake_state, vote_state, stake_history, new_warmup_cooldown_rate_epoch, &account_points );
if ( FD_UNLIKELY( err ) ) {
FD_LOG_DEBUG(( "failed to calculate points" ));
continue;
Expand All @@ -524,6 +535,12 @@ calculate_stake_vote_rewards_account(
fd_calculate_stake_vote_rewards_result_t * result
) {
FD_SCRATCH_SCOPE_BEGIN {
int _err[1];
ulong * new_warmup_cooldown_rate_epoch = fd_scratch_alloc( alignof(ulong), sizeof(ulong) );
int is_some = fd_new_warmup_cooldown_rate_epoch( slot_ctx, new_warmup_cooldown_rate_epoch, _err );
if( FD_UNLIKELY( !is_some ) ) {
new_warmup_cooldown_rate_epoch = NULL;
}

fd_epoch_bank_t const * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
ulong minimum_stake_delegation = get_minimum_stake_delegation( slot_ctx );
Expand Down Expand Up @@ -578,7 +595,7 @@ calculate_stake_vote_rewards_account(

/* Note, this doesn't actually redeem any rewards.. this is a misnomer. */
fd_calculated_stake_rewards_t calculated_stake_rewards[1] = {0};
int err = redeem_rewards( stake_history, stake_state, vote_state_versioned, rewarded_epoch, point_value, calculated_stake_rewards );
int err = redeem_rewards( stake_history, stake_state, vote_state_versioned, rewarded_epoch, point_value, new_warmup_cooldown_rate_epoch, calculated_stake_rewards );
if ( err != 0) {
FD_LOG_DEBUG(( "redeem_rewards failed for %s with error %d", FD_BASE58_ENC_32_ALLOCA( stake_acc->key ), err ));
return;
Expand Down Expand Up @@ -1114,6 +1131,7 @@ fd_begin_partitioned_rewards(
const fd_hash_t * parent_blockhash,
ulong parent_epoch
) {
FD_SCRATCH_SCOPE_BEGIN {
/* https://github.com/anza-xyz/agave/blob/7117ed9653ce19e8b2dea108eff1f3eb6a3378a7/runtime/src/bank/partitioned_epoch_rewards/calculation.rs#L55 */
fd_calculate_rewards_and_distribute_vote_rewards_result_t rewards_result[1] = {0};
calculate_rewards_and_distribute_vote_rewards(
Expand Down Expand Up @@ -1141,6 +1159,7 @@ fd_begin_partitioned_rewards(
rewards_result->point_value,
parent_blockhash
);
} FD_SCRATCH_SCOPE_END;
}

/*
Expand Down
12 changes: 10 additions & 2 deletions src/flamenco/runtime/fd_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4534,8 +4534,16 @@ void fd_process_new_epoch(
else if (FD_FEATURE_ACTIVE(slot_ctx, update_hashes_per_tick2))
epoch_bank->hashes_per_tick = UPDATED_HASHES_PER_TICK2;

/* Get the new rate activation epoch */
int _err[1];
ulong * new_rate_activation_epoch = fd_scratch_alloc( alignof(ulong), sizeof(ulong) );
int is_some = fd_new_warmup_cooldown_rate_epoch( slot_ctx, new_rate_activation_epoch, _err );
if( FD_UNLIKELY( !is_some ) ) {
new_rate_activation_epoch = NULL;
}

/* Updates stake history sysvar accumulated values. */
fd_stakes_activate_epoch( slot_ctx );
fd_stakes_activate_epoch( slot_ctx, new_rate_activation_epoch );

/* Update the stakes epoch value to the new epoch */
epoch_bank->stakes.epoch = epoch;
Expand All @@ -4560,7 +4568,7 @@ void fd_process_new_epoch(
fd_stake_history_t const * history = fd_sysvar_cache_stake_history( slot_ctx->sysvar_cache );
if( FD_UNLIKELY( !history ) ) FD_LOG_ERR(( "StakeHistory sysvar is missing from sysvar cache" ));

refresh_vote_accounts( slot_ctx, history );
refresh_vote_accounts( slot_ctx, history, new_rate_activation_epoch );
fd_update_stake_delegations( slot_ctx );

/* Replace stakes at T-2 (slot_ctx->slot_bank.epoch_stakes) by stakes at T-1 (epoch_bank->next_epoch_stakes) */
Expand Down
28 changes: 16 additions & 12 deletions src/flamenco/runtime/program/fd_stake_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,20 +715,24 @@ stake_deactivate( fd_stake_t * stake, ulong epoch, uint * custom_err ) {
}

// https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L62
static inline int
new_warmup_cooldown_rate_epoch( fd_exec_instr_ctx_t const * invoke_context,
/* out */ ulong * epoch,
int * err ) {
int
fd_new_warmup_cooldown_rate_epoch( fd_exec_slot_ctx_t const * slot_ctx,
/* out */ ulong * epoch,
int * err ) {
*err = 0;
fd_epoch_schedule_t const * epoch_schedule = fd_sysvar_cache_epoch_schedule( invoke_context->slot_ctx->sysvar_cache );
fd_epoch_schedule_t const * epoch_schedule = fd_sysvar_cache_epoch_schedule( slot_ctx->sysvar_cache );
if( FD_UNLIKELY( !epoch_schedule ) ) {
*epoch = ULONG_MAX;
*err = FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
return 1;
}
ulong slot = invoke_context->epoch_ctx->features.reduce_stake_warmup_cooldown;
*epoch = fd_slot_to_epoch( epoch_schedule, slot, NULL );
return 1;
/* reduce_stake_warmup_cooldown is activated on all clusters, so we shouldn't have a `None` case. */
if( FD_LIKELY( FD_FEATURE_ACTIVE( slot_ctx, reduce_stake_warmup_cooldown ) ) ) {
ulong slot = slot_ctx->epoch_ctx->features.reduce_stake_warmup_cooldown;
*epoch = fd_slot_to_epoch( epoch_schedule, slot, NULL );
return 1;
}
return 0;
}

/**********************************************************************/
Expand Down Expand Up @@ -793,7 +797,7 @@ get_if_mergeable( fd_exec_instr_ctx_t * invoke_context, // not const to
ulong new_rate_activation_epoch = ULONG_MAX;
int err;
// https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1111
int is_some = new_warmup_cooldown_rate_epoch( invoke_context, &new_rate_activation_epoch, &err );
int is_some = fd_new_warmup_cooldown_rate_epoch( invoke_context->slot_ctx, &new_rate_activation_epoch, &err );
if( FD_UNLIKELY( err ) ) return err;

// https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_state.rs#L1108
Expand Down Expand Up @@ -1102,7 +1106,7 @@ get_stake_status( fd_exec_instr_ctx_t const * invoke_context,
return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
ulong new_rate_activation_epoch = ULONG_MAX;
int err;
int is_some = new_warmup_cooldown_rate_epoch( invoke_context, &new_rate_activation_epoch, &err );
int is_some = fd_new_warmup_cooldown_rate_epoch( invoke_context->slot_ctx, &new_rate_activation_epoch, &err );
if( FD_UNLIKELY( err ) ) return err;

*out =
Expand Down Expand Up @@ -1137,7 +1141,7 @@ redelegate_stake( fd_exec_instr_ctx_t const * ctx,
uint * custom_err ) {
ulong new_rate_activation_epoch = ULONG_MAX;
int err;
int is_some = new_warmup_cooldown_rate_epoch( ctx, &new_rate_activation_epoch, &err );
int is_some = fd_new_warmup_cooldown_rate_epoch( ctx->slot_ctx, &new_rate_activation_epoch, &err );
if( FD_UNLIKELY( err ) ) return err;

// FIXME FD_LIKELY
Expand Down Expand Up @@ -2734,7 +2738,7 @@ fd_stake_program_execute( fd_exec_instr_ctx_t * ctx ) {
uchar custodian_index = 5;
ulong new_rate_activation_epoch = ULONG_MAX;
int err;
int is_some = new_warmup_cooldown_rate_epoch( ctx, &new_rate_activation_epoch, &err );
int is_some = fd_new_warmup_cooldown_rate_epoch( ctx->slot_ctx, &new_rate_activation_epoch, &err );
if( FD_UNLIKELY( err ) ) return err;

// https://github.com/anza-xyz/agave/blob/c8685ce0e1bb9b26014f1024de2cd2b8c308cbde/programs/stake/src/stake_instruction.rs#L200
Expand Down
5 changes: 5 additions & 0 deletions src/flamenco/runtime/program/fd_stake_program.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

FD_PROTOTYPES_BEGIN

int
fd_new_warmup_cooldown_rate_epoch( fd_exec_slot_ctx_t const * slot_ctx,
/* out */ ulong * epoch,
int * err );

/* fd_stake_program_execute is the instruction processing entrypoint
for the stake program. On return, ctx.txn_ctx->dirty_stake_acc==1 if
a stake account may have been modified. */
Expand Down
1 change: 1 addition & 0 deletions src/flamenco/runtime/tests/run_ledger_tests_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,4 @@ src/flamenco/runtime/tests/run_ledger_test.sh -l mainnet-301359740 -s snapshot-3
src/flamenco/runtime/tests/run_ledger_test.sh -l testnet-302734641 -s snapshot-302734640-9e44jEVavfHC253DSBGSjTFt2diZrgcMHTRZtpUvisvr.tar.zst -p 50 -y 16 -m 5000000 -e 302734658 -c 2.0.10
src/flamenco/runtime/tests/run_ledger_test.sh -l migrate-feature-program -s snapshot-500-Cz6iotFK7kNcGTpyUZeX4CHbT2uff2uzVW8RXXysBnVk.tar.zst -p 50 -y 16 -m 5000000 -e 675 -c 2.1.0 -o 4eohviozzEeivk1y9UbrnekbAFMDQyJz5JjA9Y6gyvky
src/flamenco/runtime/tests/run_ledger_test.sh -l migrate-config-program -s snapshot-500-HCg5AHVPC6JAqZo4p6iMcDmo586ZjkxxPpxfAwCHqroy.tar.zst -p 50 -y 16 -m 5000000 -e 675 -c 2.1.0 -o 2Fr57nzzkLYXW695UdDxDeR5fhnZWSttZeZYemrnpGFV
src/flamenco/runtime/tests/run_ledger_test.sh -l per-stake-history-new-rate-activation-epoch -s snapshot-50-47DbuHpi6gXmZKQ1FUSAAfkgnuWrkfTAtx3Hk5Gqsu5W.tar.zst -p 50 -y 16 -m 5000000 -e 675 -c 2.1.0
8 changes: 4 additions & 4 deletions src/flamenco/stakes/fd_stakes.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ stake account.
https://github.com/solana-labs/solana/blob/c091fd3da8014c0ef83b626318018f238f506435/runtime/src/stakes.rs#L562 */
void
refresh_vote_accounts( fd_exec_slot_ctx_t * slot_ctx,
fd_stake_history_t const * history ) {
fd_stake_history_t const * history,
ulong * new_rate_activation_epoch ) {
fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
fd_stakes_t * stakes = &epoch_bank->stakes;

Expand All @@ -171,7 +172,6 @@ refresh_vote_accounts( fd_exec_slot_ctx_t * slot_ctx,
void * mem = fd_scratch_alloc( fd_stake_weight_t_map_align(), fd_stake_weight_t_map_footprint(maplen));
fd_stake_weight_t_mapnode_t * pool = fd_stake_weight_t_map_join(fd_stake_weight_t_map_new(mem, maplen));
fd_stake_weight_t_mapnode_t * root = NULL;
ulong * new_rate_activation_epoch = NULL;

// Iterate over each stake delegation and accumulate the stake amount associated with the given vote account.
for (
Expand Down Expand Up @@ -276,7 +276,8 @@ refresh_vote_accounts( fd_exec_slot_ctx_t * slot_ctx,

/* https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/runtime/src/stakes.rs#L169 */
void
fd_stakes_activate_epoch( fd_exec_slot_ctx_t * slot_ctx) {
fd_stakes_activate_epoch( fd_exec_slot_ctx_t * slot_ctx,
ulong * new_rate_activation_epoch ) {

fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
fd_stakes_t * stakes = &epoch_bank->stakes;
Expand All @@ -298,7 +299,6 @@ fd_stakes_activate_epoch( fd_exec_slot_ctx_t * slot_ctx) {
fd_stake_weight_t_mapnode_t * pool = fd_stake_weight_t_map_alloc(slot_ctx->valloc, 10000);
fd_stake_weight_t_mapnode_t * root = NULL;

ulong * new_rate_activation_epoch = NULL;
for ( fd_delegation_pair_t_mapnode_t * n = fd_delegation_pair_t_map_minimum(stakes->stake_delegations_pool, stakes->stake_delegations_root); n; n = fd_delegation_pair_t_map_successor(stakes->stake_delegations_pool, n) ) {
FD_BORROWED_ACCOUNT_DECL(acc);
int rc = fd_acc_mgr_view(slot_ctx->acc_mgr, slot_ctx->funk_txn, &n->elem.account, acc);
Expand Down
6 changes: 4 additions & 2 deletions src/flamenco/stakes/fd_stakes.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ fd_stake_weights_by_node( fd_vote_accounts_t const * accs,


void
fd_stakes_activate_epoch( fd_exec_slot_ctx_t * global );
fd_stakes_activate_epoch( fd_exec_slot_ctx_t * slot_ctx,
ulong * new_rate_activation_epoch );

fd_stake_history_entry_t stake_and_activating( fd_delegation_t const * delegation, ulong target_epoch, fd_stake_history_t * stake_history, ulong * new_rate_activation_epoch );

Expand All @@ -47,7 +48,8 @@ fd_stakes_upsert_stake_delegation( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_ac

void
refresh_vote_accounts( fd_exec_slot_ctx_t * slot_ctx,
fd_stake_history_t const * history );
fd_stake_history_t const * history,
ulong * new_rate_activation_epoch );

FD_PROTOTYPES_END

Expand Down

0 comments on commit 4a8027f

Please sign in to comment.