Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flamenco: no more custom votes anywhere #4202

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions book/guide/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ user = "firedancer"

This configuration will cause Firedancer to run as the user `firedancer`
on the local machine. The `identity_path` and `vote_account_path` should
be Agave style keys, which can be generated with the Solana Labs cli.
be Agave style keys, which can be generated with the Solana Labs cli.

This will put the ledger in `/home/firedancer/.firedancer/fd1/ledger`.
To customize this path, refer to the [configuration
Expand Down Expand Up @@ -322,7 +322,7 @@ vary across drivers. Popular well tested drivers include:
- `ice` — Intel E800 series

Firedancer installs an XDP program on the network interface
`[tiles.net.interface]` and `lo` while it is running. This program
`[tiles.net.interface]` and `lo` while it is running. This program
redirects traffic on ports that Firedancer is listening on via `AF_XDP`.
Traffic targeting any other applications (e.g. an SSH or HTTP server
running on the system) passes through as usual. The XDP program is
Expand Down
36 changes: 33 additions & 3 deletions src/app/fdctl/run/tiles/fd_replay.c
Original file line number Diff line number Diff line change
Expand Up @@ -2364,13 +2364,43 @@ publish_votes_to_plugin( fd_replay_tile_ctx_t * ctx,
n && i < FD_CLUSTER_NODE_CNT;
n = fd_vote_accounts_pair_t_map_successor_const( pool, n ) ) {
if( n->elem.stake == 0 ) continue;

/* TODO: Define a helper that gets specific fields. */
fd_bincode_decode_ctx_t dec_ctx = {
.data = n->elem.value.data,
.dataend = n->elem.value.data + n->elem.value.data_len,
.valloc = fd_spad_virtual( ctx->runtime_spad )
};

fd_vote_state_versioned_t vsv[1];
fd_vote_state_versioned_decode( vsv, &dec_ctx );

fd_pubkey_t node_pubkey;
ulong last_ts_slot;
switch( vsv->discriminant ) {
case fd_vote_state_versioned_enum_v0_23_5:
node_pubkey = vsv->inner.v0_23_5.node_pubkey;
last_ts_slot = vsv->inner.v0_23_5.last_timestamp.slot;
break;
case fd_vote_state_versioned_enum_v1_14_11:
node_pubkey = vsv->inner.v1_14_11.node_pubkey;
last_ts_slot = vsv->inner.v1_14_11.last_timestamp.slot;
break;
case fd_vote_state_versioned_enum_current:
node_pubkey = vsv->inner.current.node_pubkey;
last_ts_slot = vsv->inner.current.last_timestamp.slot;
break;
default:
__builtin_unreachable();
}

Comment on lines +2380 to +2396
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be nice in future prs to define getters for these fields, possibly in fd types

fd_vote_update_msg_t * msg = (fd_vote_update_msg_t *)(dst + sizeof(ulong) + i*112U);
memset( msg, 0, 112U );
memcpy( msg->vote_pubkey, n->elem.key.uc, sizeof(fd_pubkey_t) );
memcpy( msg->node_pubkey, n->elem.value.node_pubkey.uc, sizeof(fd_pubkey_t) );
memcpy( msg->node_pubkey, node_pubkey.uc, sizeof(fd_pubkey_t) );
msg->activated_stake = n->elem.stake;
msg->last_vote = n->elem.value.last_timestamp_slot;
msg->is_delinquent = (uchar)(msg->last_vote == 0);
msg->last_vote = last_ts_slot;
msg->is_delinquent = (uchar)(msg->last_vote == 0);
++i;
}

Expand Down
17 changes: 10 additions & 7 deletions src/disco/rpcserver/fd_rpc_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -1711,13 +1711,16 @@ method_getVersion(struct json_values* values, fd_rpc_ctx_t * ctx) {

static void
vote_account_to_json(fd_webserver_t * ws, fd_vote_accounts_pair_t_mapnode_t const * vote_node) {
char pubkey[50];
fd_base58_encode_32(vote_node->elem.value.node_pubkey.uc, 0, pubkey);
char key[50];
fd_base58_encode_32(vote_node->elem.key.uc, 0, key);
// TODO: epochCredits and lastVote
fd_web_reply_sprintf(ws, "{\"commission\":0,\"epochVoteAccount\":true,\"epochCredits\":[],\"nodePubkey\":\"%s\",\"lastVote\":%lu,\"activatedStake\":%lu,\"votePubkey\":\"%s\",\"rootSlot\":0}",
pubkey, vote_node->elem.value.last_timestamp_slot, vote_node->elem.stake, key);
(void)ws;
(void)vote_node;
/* TODO: This needs to be fixed to work with new vote cache. */
// char pubkey[50];
// fd_base58_encode_32(vote_node->elem.value.node_pubkey.uc, 0, pubkey);
// char key[50];
// fd_base58_encode_32(vote_node->elem.key.uc, 0, key);
// // TODO: epochCredits and lastVote
// fd_web_reply_sprintf(ws, "{\"commission\":0,\"epochVoteAccount\":true,\"epochCredits\":[],\"nodePubkey\":\"%s\",\"lastVote\":%lu,\"activatedStake\":%lu,\"votePubkey\":\"%s\",\"rootSlot\":0}",
// pubkey, vote_node->elem.value.last_timestamp_slot, vote_node->elem.stake, key);
}

// Implementation of the "getVoteAccounts" methods
Expand Down
30 changes: 19 additions & 11 deletions src/flamenco/rewards/fd_rewards.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ get_inflation_num_slots( fd_exec_slot_ctx_t * slot_ctx,
ulong slot ) {
ulong inflation_activation_slot = get_inflation_start_slot( slot_ctx );
ulong inflation_start_slot = fd_epoch_slot0( epoch_schedule,
fd_ulong_sat_sub( fd_slot_to_epoch( epoch_schedule,
inflation_activation_slot, NULL ),
fd_ulong_sat_sub( fd_slot_to_epoch( epoch_schedule,
inflation_activation_slot, NULL ),
1UL ) );

ulong epoch = fd_slot_to_epoch( epoch_schedule, slot, NULL );
Expand Down Expand Up @@ -388,7 +388,7 @@ calculate_reward_points_partitioned( fd_exec_slot_ctx_t * slot_ctx,
.total_points = &points,
};

fd_tpool_exec_all_batch( tpool, 0UL, fd_tpool_worker_cnt( tpool ), calculate_points_tpool,
fd_tpool_exec_all_batch( tpool, 0UL, fd_tpool_worker_cnt( tpool ), calculate_points_tpool,
temp_info->stake_infos, &task_args, NULL, 1UL, 0UL, temp_info->stake_infos_len );

if( points > 0 ) {
Expand Down Expand Up @@ -427,7 +427,7 @@ calculate_stake_vote_rewards_account_tpool( void *tpool,
/* Build a local vote reward map */
fd_vote_reward_t_mapnode_t * vote_reward_map_pool = fd_vote_reward_t_map_join( fd_vote_reward_t_map_new( fd_spad_alloc( spad,
fd_vote_reward_t_map_align(),
fd_vote_reward_t_map_footprint( m1-m0 )),
fd_vote_reward_t_map_footprint( m1-m0 )),
m1-m0 ) );
fd_vote_reward_t_mapnode_t * vote_reward_map_root = NULL;

Expand All @@ -445,7 +445,9 @@ calculate_stake_vote_rewards_account_tpool( void *tpool,
fd_pubkey_t const * voter_acc = &stake->delegation.voter_pubkey;
fd_vote_info_pair_t_mapnode_t key;
fd_memcpy( &key.elem.account, voter_acc, sizeof(fd_pubkey_t) );
fd_vote_info_pair_t_mapnode_t * vote_state_entry = fd_vote_info_pair_t_map_find( temp_info->vote_states_pool, temp_info->vote_states_root, &key );
fd_vote_info_pair_t_mapnode_t * vote_state_entry = fd_vote_info_pair_t_map_find( temp_info->vote_states_pool,
temp_info->vote_states_root,
&key );
if( FD_UNLIKELY( vote_state_entry==NULL ) ) {
continue;
}
Expand All @@ -454,7 +456,13 @@ calculate_stake_vote_rewards_account_tpool( void *tpool,

/* 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, vote_state, rewarded_epoch, point_value, new_warmup_cooldown_rate_epoch, calculated_stake_rewards );
int err = redeem_rewards( stake_history,
stake,
vote_state,
rewarded_epoch,
point_value,
new_warmup_cooldown_rate_epoch,
calculated_stake_rewards );
if( FD_UNLIKELY( err!=0 ) ) {
FD_LOG_DEBUG(( "redeem_rewards failed for %s with error %d", FD_BASE58_ENC_32_ALLOCA( stake_acc->key ), err ));
continue;
Expand Down Expand Up @@ -572,7 +580,7 @@ calculate_stake_vote_rewards( fd_exec_slot_ctx_t * slot_ct
/* Create the stake rewards pool and dlist. The pool will be destoyed after the stake rewards have been distributed. */
result->stake_reward_calculation.pool = fd_stake_reward_pool_join( fd_stake_reward_pool_new( fd_spad_alloc( runtime_spad,
fd_stake_reward_pool_align(),
fd_stake_reward_pool_footprint( rewards_max_count ) ),
fd_stake_reward_pool_footprint( rewards_max_count ) ),
rewards_max_count ) );
fd_stake_reward_dlist_new( &result->stake_reward_calculation.stake_rewards );
result->stake_reward_calculation.stake_rewards_len = 0UL;
Expand All @@ -581,7 +589,7 @@ calculate_stake_vote_rewards( fd_exec_slot_ctx_t * slot_ct
ulong vote_account_cnt = fd_vote_info_pair_t_map_size( temp_info->vote_states_pool, temp_info->vote_states_root );
result->vote_reward_map_pool = fd_vote_reward_t_map_join( fd_vote_reward_t_map_new( fd_spad_alloc( runtime_spad,
fd_vote_reward_t_map_align(),
fd_vote_reward_t_map_footprint( vote_account_cnt )),
fd_vote_reward_t_map_footprint( vote_account_cnt )),
vote_account_cnt ) );
result->vote_reward_map_root = NULL;

Expand Down Expand Up @@ -624,7 +632,7 @@ calculate_stake_vote_rewards( fd_exec_slot_ctx_t * slot_ct

/* Loop over all the delegations
https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/calculation.rs#L367 */
fd_tpool_exec_all_batch( tpool, 0UL, fd_tpool_worker_cnt( tpool ), calculate_stake_vote_rewards_account_tpool,
fd_tpool_exec_all_batch( tpool, 0UL, fd_tpool_worker_cnt( tpool ), calculate_stake_vote_rewards_account_tpool,
temp_info, &task_args, NULL, 1UL, 0UL, temp_info->stake_infos_len );
}

Expand Down Expand Up @@ -684,7 +692,7 @@ get_reward_distribution_num_blocks( fd_epoch_schedule_t const * epoch_schedule,

ulong num_chunks = total_stake_accounts / (ulong)STAKE_ACCOUNT_STORES_PER_BLOCK + (total_stake_accounts % STAKE_ACCOUNT_STORES_PER_BLOCK != 0);
num_chunks = fd_ulong_max( num_chunks, 1UL );
num_chunks = fd_ulong_min( num_chunks,
num_chunks = fd_ulong_min( num_chunks,
fd_ulong_max( epoch_schedule->slots_per_epoch / (ulong)MAX_FACTOR_OF_REWARD_BLOCKS_IN_EPOCH, 1UL ) );
return num_chunks;
}
Expand Down Expand Up @@ -1084,7 +1092,7 @@ fd_begin_partitioned_rewards( fd_exec_slot_ctx_t * slot_ctx,

/* Set the epoch reward status to be active */
set_epoch_reward_status_active( slot_ctx,
distribution_starting_block_height,
distribution_starting_block_height,
&rewards_result->stake_rewards_by_partition.partitioned_stake_rewards );

/* Initialize the epoch rewards sysvar
Expand Down
42 changes: 34 additions & 8 deletions src/flamenco/runtime/context/fd_exec_slot_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fd_exec_slot_ctx_delete( void * mem ) {
accounts in current epoch stakes. */

static int
recover_clock( fd_exec_slot_ctx_t * slot_ctx ) {
recover_clock( fd_exec_slot_ctx_t * slot_ctx, fd_spad_t * runtime_spad ) {

fd_epoch_bank_t const * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
fd_vote_accounts_t const * vote_accounts = &epoch_bank->stakes.vote_accounts;
Expand All @@ -114,14 +114,40 @@ recover_clock( fd_exec_slot_ctx_t * slot_ctx ) {

/* Extract vote timestamp of account */

fd_vote_block_timestamp_t vote_state_timestamp = {
.timestamp = n->elem.value.last_timestamp_ts,
.slot = n->elem.value.last_timestamp_slot
};

fd_bincode_decode_ctx_t ctx = {
.data = n->elem.value.data,
.dataend = n->elem.value.data + n->elem.value.data_len,
.valloc = fd_spad_virtual( runtime_spad )
};

fd_vote_state_versioned_t vsv[1];
fd_vote_state_versioned_decode( vsv, &ctx );

long timestamp = 0;
ulong slot = 0;
switch( vsv->discriminant ) {
case fd_vote_state_versioned_enum_v0_23_5:
timestamp = vsv->inner.v0_23_5.last_timestamp.timestamp;
slot = vsv->inner.v0_23_5.last_timestamp.slot;
break;
case fd_vote_state_versioned_enum_v1_14_11:
timestamp = vsv->inner.v1_14_11.last_timestamp.timestamp;
slot = vsv->inner.v1_14_11.last_timestamp.slot;
break;
case fd_vote_state_versioned_enum_current:
timestamp = vsv->inner.current.last_timestamp.timestamp;
slot = vsv->inner.current.last_timestamp.slot;
break;
default:
__builtin_unreachable();
}



/* Record timestamp */
if( vote_state_timestamp.slot != 0 || n->elem.stake != 0 ) {
fd_vote_record_timestamp_vote_with_slot( slot_ctx, &n->elem.key, vote_state_timestamp.timestamp, vote_state_timestamp.slot );
if( slot != 0 || n->elem.stake != 0 ) {
fd_vote_record_timestamp_vote_with_slot( slot_ctx, &n->elem.key, timestamp, slot );
}
}

Expand Down Expand Up @@ -281,7 +307,7 @@ fd_exec_slot_ctx_recover_( fd_exec_slot_ctx_t * slot_ctx,
if( !slot_ctx->slot_bank.timestamp_votes.votes_pool ) {
slot_ctx->slot_bank.timestamp_votes.votes_pool = fd_clock_timestamp_vote_t_map_alloc( fd_spad_virtual( runtime_spad ),15000UL );
}
recover_clock( slot_ctx );
recover_clock( slot_ctx, runtime_spad );

/* Pass in the hard forks */

Expand Down
121 changes: 73 additions & 48 deletions src/flamenco/runtime/fd_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,31 @@ fd_runtime_distribute_rent_to_validators( fd_exec_slot_ctx_t * slot_ctx,
n;
n = fd_vote_accounts_pair_t_map_successor( vote_accounts_pool, n ), i++) {

validator_stakes[i].pubkey = n->elem.value.node_pubkey;
fd_bincode_decode_ctx_t ctx = {
.data = n->elem.value.data,
.dataend = n->elem.value.data + n->elem.value.data_len,
.valloc = fd_spad_virtual( runtime_spad )
};

fd_vote_state_versioned_t vsv[1];
fd_vote_state_versioned_decode( vsv, &ctx );

fd_pubkey_t node_pubkey;
switch( vsv->discriminant ) {
case fd_vote_state_versioned_enum_v0_23_5:
node_pubkey = vsv->inner.v0_23_5.node_pubkey;
break;
case fd_vote_state_versioned_enum_v1_14_11:
node_pubkey = vsv->inner.v1_14_11.node_pubkey;
break;
case fd_vote_state_versioned_enum_current:
node_pubkey = vsv->inner.current.node_pubkey;
break;
default:
__builtin_unreachable();
}

validator_stakes[i].pubkey = node_pubkey;
validator_stakes[i].stake = n->elem.stake;

total_staked += n->elem.stake;
Expand Down Expand Up @@ -3141,53 +3165,54 @@ fd_runtime_init_bank_from_genesis( fd_exec_slot_ctx_t * slot_ctx,
fd_vote_accounts_pair_t_mapnode_t *node = fd_vote_accounts_pair_t_map_acquire(vacc_pool);
FD_TEST( node );

fd_vote_block_timestamp_t last_timestamp = {0};
fd_pubkey_t node_pubkey = {0};
FD_SPAD_FRAME_BEGIN( runtime_spad ) {
/* Deserialize content */
fd_vote_state_versioned_t vs[1];
fd_bincode_decode_ctx_t decode = {
.data = acc->account.data,
.dataend = acc->account.data + acc->account.data_len,
.valloc = fd_spad_virtual( runtime_spad )
};
int decode_err = fd_vote_state_versioned_decode( vs, &decode );
if( FD_UNLIKELY( decode_err!=FD_BINCODE_SUCCESS ) ) {
FD_LOG_WARNING(( "fd_vote_state_versioned_decode failed (%d)", decode_err ));
return;
}

switch( vs->discriminant )
{
case fd_vote_state_versioned_enum_current:
last_timestamp = vs->inner.current.last_timestamp;
node_pubkey = vs->inner.current.node_pubkey;
break;
case fd_vote_state_versioned_enum_v0_23_5:
last_timestamp = vs->inner.v0_23_5.last_timestamp;
node_pubkey = vs->inner.v0_23_5.node_pubkey;
break;
case fd_vote_state_versioned_enum_v1_14_11:
last_timestamp = vs->inner.v1_14_11.last_timestamp;
node_pubkey = vs->inner.v1_14_11.node_pubkey;
break;
default:
__builtin_unreachable();
}

} FD_SPAD_FRAME_END;

fd_memcpy(node->elem.key.key, acc->key.key, sizeof(fd_pubkey_t));
node->elem.stake = acc->account.lamports;
node->elem.value = (fd_solana_vote_account_t){
.lamports = acc->account.lamports,
.node_pubkey = node_pubkey,
.last_timestamp_ts = last_timestamp.timestamp,
.last_timestamp_slot = last_timestamp.slot,
.owner = acc->account.owner,
.executable = acc->account.executable,
.rent_epoch = acc->account.rent_epoch
};
/* FIXME: Reimplement when we try to fix genesis. */
// fd_vote_block_timestamp_t last_timestamp = {0};
// fd_pubkey_t node_pubkey = {0};
// 1FD_SPAD_FRAME_BEGIN( runtime_spad ) {
// /* Deserialize content */
// fd_vote_state_versioned_t vs[1];
// fd_bincode_decode_ctx_t decode = {
// .data = acc->account.data,
// .dataend = acc->account.data + acc->account.data_len,
// .valloc = fd_spad_virtual( runtime_spad )
// };
// int decode_err = fd_vote_state_versioned_decode( vs, &decode );
// if( FD_UNLIKELY( decode_err!=FD_BINCODE_SUCCESS ) ) {
// FD_LOG_WARNING(( "fd_vote_state_versioned_decode failed (%d)", decode_err ));
// return;
// }

// switch( vs->discriminant )
// {
// case fd_vote_state_versioned_enum_current:
// last_timestamp = vs->inner.current.last_timestamp;
// node_pubkey = vs->inner.current.node_pubkey;
// break;
// case fd_vote_state_versioned_enum_v0_23_5:
// last_timestamp = vs->inner.v0_23_5.last_timestamp;
// node_pubkey = vs->inner.v0_23_5.node_pubkey;
// break;
// case fd_vote_state_versioned_enum_v1_14_11:
// last_timestamp = vs->inner.v1_14_11.last_timestamp;
// node_pubkey = vs->inner.v1_14_11.node_pubkey;
// break;
// default:
// __builtin_unreachable();
// }

// } FD_SPAD_FRAME_END;

// fd_memcpy(node->elem.key.key, acc->key.key, sizeof(fd_pubkey_t));
// node->elem.stake = acc->account.lamports;
// node->elem.value = (fd_solana_vote_account_t){
// .lamports = acc->account.lamports,
// .node_pubkey = node_pubkey,
// .last_timestamp_ts = last_timestamp.timestamp,
// .last_timestamp_slot = last_timestamp.slot,
// .owner = acc->account.owner,
// .executable = acc->account.executable,
// .rent_epoch = acc->account.rent_epoch
// };

fd_vote_accounts_pair_t_map_insert( vacc_pool, &vacc_root, node );

Expand Down
Loading
Loading