Skip to content

runtime: replace fd_vote_accounts_global [wip] #5953

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
96 changes: 96 additions & 0 deletions src/flamenco/runtime/context/fd_exec_slot_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,102 @@ fd_exec_slot_ctx_recover( fd_exec_slot_ctx_t * slot_ctx,
fd_vote_accounts_vote_accounts_root_update( curr_epoch_stakes, curr_epoch_stakes_root );
fd_bank_curr_epoch_stakes_end_locking_modify( slot_ctx->bank );

fd_vote_states_t * vote_states = fd_vote_states_join( fd_vote_states_new( fd_bank_vote_states_locking_modify( slot_ctx->bank ), FD_RUNTIME_MAX_VOTE_ACCOUNTS ) );
if( FD_UNLIKELY( !vote_states ) ) {
FD_LOG_CRIT(( "unable to join vote states" ));
}

for( fd_vote_accounts_pair_global_t_mapnode_t * n = fd_vote_accounts_pair_global_t_map_minimum( manifest_vote_accounts_pool, manifest_vote_accounts_root );
n;
n = fd_vote_accounts_pair_global_t_map_successor( manifest_vote_accounts_pool, n ) ) {

ulong data_len = n->elem.value.data_len;
uchar * manifest_data = fd_solana_account_data_join( &n->elem.value );

uchar data[5000UL];
fd_bincode_decode_static(
vote_state_versioned,
data,
manifest_data,
data_len,
&decode_err );

fd_vote_state_versioned_t * vsv = (fd_vote_state_versioned_t *)data;

uchar comission;
ulong credits_cnt = 0UL;
ushort epoch[EPOCH_CREDITS_MAX];
ulong credits[EPOCH_CREDITS_MAX];
ulong prev_credits[EPOCH_CREDITS_MAX];

fd_vote_epoch_credits_t * epoch_credits = NULL;


switch( vsv->discriminant ) {
case fd_vote_state_versioned_enum_v0_23_5:
comission = vsv->inner.v0_23_5.commission;

epoch_credits = vsv->inner.v0_23_5.epoch_credits;

for( deq_fd_vote_epoch_credits_t_iter_t iter = deq_fd_vote_epoch_credits_t_iter_init( epoch_credits );
!deq_fd_vote_epoch_credits_t_iter_done( epoch_credits, iter );
iter = deq_fd_vote_epoch_credits_t_iter_next( epoch_credits, iter ) ) {

fd_vote_epoch_credits_t * ele = deq_fd_vote_epoch_credits_t_iter_ele( epoch_credits, iter );

epoch[credits_cnt] = (ushort)ele->epoch;
credits[credits_cnt] = ele->credits;
prev_credits[credits_cnt] = ele->prev_credits;
credits_cnt++;
}

break;
case fd_vote_state_versioned_enum_v1_14_11:
comission = vsv->inner.v1_14_11.commission;

epoch_credits = vsv->inner.v1_14_11.epoch_credits;

for( deq_fd_vote_epoch_credits_t_iter_t iter = deq_fd_vote_epoch_credits_t_iter_init( epoch_credits );
!deq_fd_vote_epoch_credits_t_iter_done( epoch_credits, iter );
iter = deq_fd_vote_epoch_credits_t_iter_next( epoch_credits, iter ) ) {

fd_vote_epoch_credits_t * ele = deq_fd_vote_epoch_credits_t_iter_ele( epoch_credits, iter );

epoch[credits_cnt] = (ushort)ele->epoch;
credits[credits_cnt] = ele->credits;
prev_credits[credits_cnt] = ele->prev_credits;
credits_cnt++;
}
break;
case fd_vote_state_versioned_enum_current:
comission = vsv->inner.current.commission;
epoch_credits = vsv->inner.current.epoch_credits;

for( deq_fd_vote_epoch_credits_t_iter_t iter = deq_fd_vote_epoch_credits_t_iter_init( epoch_credits );
!deq_fd_vote_epoch_credits_t_iter_done( epoch_credits, iter );
iter = deq_fd_vote_epoch_credits_t_iter_next( epoch_credits, iter ) ) {

fd_vote_epoch_credits_t * ele = deq_fd_vote_epoch_credits_t_iter_ele( epoch_credits, iter );

epoch[credits_cnt] = (ushort)ele->epoch;
credits[credits_cnt] = ele->credits;
prev_credits[credits_cnt] = ele->prev_credits;
credits_cnt++;
}
break;
default:
__builtin_unreachable();
}

fd_vote_states_update( vote_states, &n->elem.key, comission, n->elem.stake, credits_cnt, epoch, credits, prev_credits );

}


fd_bank_vote_states_end_locking_modify( slot_ctx->bank );



fd_bank_epoch_set( slot_ctx->bank, manifest->bank.epoch );

/* Move EpochStakes */
Expand Down
8 changes: 8 additions & 0 deletions src/flamenco/runtime/fd_bank.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "../features/fd_features.h"
#include "../rewards/fd_epoch_rewards.h"
#include "../stakes/fd_stake_delegations.h"
#include "../stakes/fd_vote_states.h"
#include "../fd_rwlock.h"
#include "fd_runtime_const.h"
#include "fd_blockhashes.h"
Expand Down Expand Up @@ -180,6 +181,7 @@ FD_PROTOTYPES_BEGIN
X(fd_rent_t, rent, sizeof(fd_rent_t), alignof(fd_rent_t), 0, 0, 0 ) /* Rent */ \
X(fd_slot_lthash_t, lthash, sizeof(fd_slot_lthash_t), alignof(fd_slot_lthash_t), 0, 0, 1 ) /* LTHash */ \
X(fd_sysvar_cache_t, sysvar_cache, sizeof(fd_sysvar_cache_t), alignof(fd_sysvar_cache_t), 0, 0, 0 ) /* Sysvar cache */ \
X(fd_vote_states_t, vote_states, FD_VOTE_STATES_FOOTPRINT, FD_VOTE_STATES_ALIGN, 1, 0, 1 ) /* Vote states */ \
X(fd_vote_accounts_global_t, next_epoch_stakes, 200000000UL, 128UL, 1, 0, 1 ) /* Next epoch stakes, ~4K per account * 50k vote accounts */ \
/* These are the stakes that determine the leader */ \
/* schedule for the upcoming epoch. If we are executing */ \
Expand Down Expand Up @@ -286,6 +288,12 @@ FD_PROTOTYPES_BEGIN
#undef POOL_NAME
#undef POOL_T

#define POOL_NAME fd_bank_vote_states_pool
#define POOL_T fd_bank_vote_states_t
#include "../../util/tmpl/fd_pool.c"
#undef POOL_NAME
#undef POOL_T

/* As mentioned above, the overall layout of the bank struct:
- Fields used for internal pool/bank management
- Non-Cow fields
Expand Down
154 changes: 84 additions & 70 deletions src/flamenco/runtime/program/fd_vote_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -2845,96 +2845,110 @@ static void
remove_vote_account( fd_txn_account_t * vote_account,
fd_bank_t * bank ) {

fd_vote_accounts_global_t * epoch_vote_accounts = fd_bank_curr_epoch_stakes_locking_modify( bank );
fd_vote_accounts_pair_global_t_mapnode_t * epoch_vote_accounts_pool = fd_vote_accounts_vote_accounts_pool_join( epoch_vote_accounts );
fd_vote_accounts_pair_global_t_mapnode_t * epoch_vote_accounts_root = fd_vote_accounts_vote_accounts_root_join( epoch_vote_accounts );
fd_vote_states_t * vote_states = fd_bank_vote_states_locking_modify( bank );

if( FD_UNLIKELY( epoch_vote_accounts_pool==NULL ) ) {
FD_LOG_DEBUG(("Vote accounts pool does not exist"));
fd_bank_curr_epoch_stakes_end_locking_modify( bank );
return;
}
fd_vote_states_remove( vote_states, vote_account->pubkey );

fd_bank_vote_states_end_locking_modify( bank );
}

fd_vote_accounts_pair_global_t_mapnode_t vote_acc;
fd_memcpy( vote_acc.elem.key.uc, vote_account->pubkey->uc, sizeof(fd_pubkey_t) );
fd_vote_accounts_pair_global_t_mapnode_t * vote_account_entry = fd_vote_accounts_pair_global_t_map_find( epoch_vote_accounts_pool, epoch_vote_accounts_root, &vote_acc );
if( FD_LIKELY( vote_account_entry ) ) {
fd_vote_accounts_pair_global_t_map_remove( epoch_vote_accounts_pool, &epoch_vote_accounts_root, vote_account_entry);
}
static void
upsert_vote_account( fd_txn_account_t * vote_account,
fd_bank_t * bank ) {

fd_vote_accounts_vote_accounts_pool_update( epoch_vote_accounts, epoch_vote_accounts_pool );
fd_vote_accounts_vote_accounts_root_update( epoch_vote_accounts, epoch_vote_accounts_root );
fd_bank_curr_epoch_stakes_end_locking_modify( bank );
fd_vote_states_t * vote_states = fd_bank_vote_states_locking_modify( bank );

fd_account_keys_global_t * vote_account_keys = fd_bank_vote_account_keys_locking_modify( bank );
fd_account_keys_pair_t_mapnode_t * vote_account_keys_pool = fd_account_keys_account_keys_pool_join( vote_account_keys );
fd_account_keys_pair_t_mapnode_t * vote_account_keys_root = fd_account_keys_account_keys_root_join( vote_account_keys );
if( fd_vote_state_versions_is_correct_and_initialized( vote_account ) ) {
uchar * acc_data = fd_txn_account_get_data( vote_account );
ulong data_len = fd_txn_account_get_data_len( vote_account );

if( FD_UNLIKELY( vote_account_keys_pool==NULL ) ) {
fd_bank_vote_account_keys_end_locking_modify( bank );
FD_LOG_DEBUG(("Vote accounts pool does not exist"));
return;
}
uchar data[5000UL];
fd_bincode_decode_static(
vote_state_versioned,
data,
acc_data,
data_len,
&decode_err );

fd_account_keys_pair_t_mapnode_t account_key;
fd_memcpy( account_key.elem.key.uc, vote_account->pubkey->uc, sizeof(fd_pubkey_t) );
fd_account_keys_pair_t_mapnode_t * account_key_entry = fd_account_keys_pair_t_map_find( vote_account_keys_pool, vote_account_keys_root, &account_key );
if( account_key_entry ) {
fd_account_keys_pair_t_map_remove( vote_account_keys_pool, &vote_account_keys_root, account_key_entry );
}
fd_vote_state_versioned_t * vsv = (fd_vote_state_versioned_t *)data;

fd_account_keys_account_keys_pool_update( vote_account_keys, vote_account_keys_pool );
uchar comission;
ulong credits_cnt = 0UL;
ushort epoch[EPOCH_CREDITS_MAX];
ulong credits[EPOCH_CREDITS_MAX];
ulong prev_credits[EPOCH_CREDITS_MAX];

fd_bank_vote_account_keys_end_locking_modify( bank );
}
fd_vote_epoch_credits_t * epoch_credits = NULL;

static void
upsert_vote_account( fd_txn_account_t * vote_account,
fd_bank_t * bank ) {
switch( vsv->discriminant ) {
case fd_vote_state_versioned_enum_v0_23_5:
comission = vsv->inner.v0_23_5.commission;

fd_vote_accounts_global_t const * vote_accounts = fd_bank_curr_epoch_stakes_locking_query( bank );
fd_vote_accounts_pair_global_t_mapnode_t * stakes_vote_accounts_pool = fd_vote_accounts_vote_accounts_pool_join( vote_accounts );
fd_vote_accounts_pair_global_t_mapnode_t * stakes_vote_accounts_root = fd_vote_accounts_vote_accounts_root_join( vote_accounts );
epoch_credits = vsv->inner.v0_23_5.epoch_credits;

fd_account_keys_global_t * vote_account_keys = fd_bank_vote_account_keys_locking_modify( bank );
fd_account_keys_pair_t_mapnode_t * vote_account_keys_pool = fd_account_keys_account_keys_pool_join( vote_account_keys );
fd_account_keys_pair_t_mapnode_t * vote_account_keys_root = fd_account_keys_account_keys_root_join( vote_account_keys );
for( deq_fd_vote_epoch_credits_t_iter_t iter = deq_fd_vote_epoch_credits_t_iter_init( epoch_credits );
!deq_fd_vote_epoch_credits_t_iter_done( epoch_credits, iter );
iter = deq_fd_vote_epoch_credits_t_iter_next( epoch_credits, iter ) ) {

if( FD_UNLIKELY( vote_account_keys_pool==NULL ) ) {
fd_bank_vote_account_keys_end_locking_modify( bank );
fd_bank_curr_epoch_stakes_end_locking_query( bank );
FD_LOG_DEBUG(( "Vote accounts pool does not exist" ));
return;
}
fd_vote_epoch_credits_t * ele = deq_fd_vote_epoch_credits_t_iter_ele( epoch_credits, iter );

if( fd_vote_state_versions_is_correct_and_initialized( vote_account ) ) {
fd_account_keys_pair_t_mapnode_t key;
fd_memcpy( &key.elem.key, vote_account->pubkey->uc, sizeof(fd_pubkey_t) );
epoch[credits_cnt] = (ushort)ele->epoch;
credits[credits_cnt] = ele->credits;
prev_credits[credits_cnt] = ele->prev_credits;
credits_cnt++;
}

fd_vote_accounts_pair_global_t_mapnode_t vote_acc;
fd_memcpy( &vote_acc.elem.key, vote_account->pubkey->uc, sizeof(fd_pubkey_t) );
break;
case fd_vote_state_versioned_enum_v1_14_11:
comission = vsv->inner.v1_14_11.commission;

// Skip duplicates
if( FD_LIKELY( fd_account_keys_pair_t_map_find( vote_account_keys_pool, vote_account_keys_root, &key ) ||
fd_vote_accounts_pair_global_t_map_find( stakes_vote_accounts_pool, stakes_vote_accounts_root, &vote_acc ) ) ) {
fd_bank_vote_account_keys_end_locking_modify( bank );
fd_bank_curr_epoch_stakes_end_locking_query( bank );
return;
}
fd_bank_curr_epoch_stakes_end_locking_query( bank );
epoch_credits = vsv->inner.v1_14_11.epoch_credits;

for( deq_fd_vote_epoch_credits_t_iter_t iter = deq_fd_vote_epoch_credits_t_iter_init( epoch_credits );
!deq_fd_vote_epoch_credits_t_iter_done( epoch_credits, iter );
iter = deq_fd_vote_epoch_credits_t_iter_next( epoch_credits, iter ) ) {

fd_vote_epoch_credits_t * ele = deq_fd_vote_epoch_credits_t_iter_ele( epoch_credits, iter );

epoch[credits_cnt] = (ushort)ele->epoch;
credits[credits_cnt] = ele->credits;
prev_credits[credits_cnt] = ele->prev_credits;
credits_cnt++;
}
break;
case fd_vote_state_versioned_enum_current:
comission = vsv->inner.current.commission;
epoch_credits = vsv->inner.current.epoch_credits;

fd_account_keys_pair_t_mapnode_t * new_node = fd_account_keys_pair_t_map_acquire( vote_account_keys_pool );
if( FD_UNLIKELY( !new_node ) ) {
FD_LOG_ERR(("Map full"));
for( deq_fd_vote_epoch_credits_t_iter_t iter = deq_fd_vote_epoch_credits_t_iter_init( epoch_credits );
!deq_fd_vote_epoch_credits_t_iter_done( epoch_credits, iter );
iter = deq_fd_vote_epoch_credits_t_iter_next( epoch_credits, iter ) ) {

fd_vote_epoch_credits_t * ele = deq_fd_vote_epoch_credits_t_iter_ele( epoch_credits, iter );

epoch[credits_cnt] = (ushort)ele->epoch;
credits[credits_cnt] = ele->credits;
prev_credits[credits_cnt] = ele->prev_credits;
credits_cnt++;
}
break;
default:
__builtin_unreachable();
}

fd_memcpy( &new_node->elem.key, vote_account->pubkey, sizeof(fd_pubkey_t));
fd_account_keys_pair_t_map_insert( vote_account_keys_pool, &vote_account_keys_root, new_node );
fd_bank_vote_account_keys_end_locking_modify( bank );
fd_vote_states_update(
vote_states,
vote_account->pubkey,
comission,
0UL,
credits_cnt,
epoch,
credits,
prev_credits );

fd_bank_vote_states_end_locking_modify( bank );

} else {
fd_bank_vote_account_keys_end_locking_modify( bank );
fd_bank_curr_epoch_stakes_end_locking_query( bank );
remove_vote_account( vote_account, bank );
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/flamenco/stakes/Local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ $(call add-objs,fd_stake_delegations,fd_flamenco)
$(call make-unit-test,test_stake_delegations,test_stake_delegations,fd_flamenco fd_ballet fd_util)
$(call run-unit-test,test_stake_delegations)

$(call add-hdrs,fd_vote_states.h)
$(call add-objs,fd_vote_states,fd_flamenco)
$(call make-unit-test,test_vote_states,test_vote_states,fd_flamenco fd_ballet fd_util)
$(call run-unit-test,test_vote_states)


# TODO this should not depend on fd_funk
ifdef FD_HAS_HOSTED
$(call make-bin,fd_stakes_from_snapshot,fd_stakes_from_snapshot,fd_flamenco fd_funk fd_ballet fd_util)
Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/stakes/fd_stake_delegations.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ulong
fd_stake_delegations_align( void ) {
/* The align of the struct should be the max of the align of the data
structures that it contains. In this case, this is the map, the
pool, and the struct itself*/
pool, and the struct itself */
return fd_ulong_max( fd_ulong_max( fd_stake_delegation_map_align(),
fd_stake_delegation_pool_align() ), alignof(fd_stake_delegations_t) );
}
Expand Down
Loading
Loading