Skip to content
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
9 changes: 9 additions & 0 deletions src/flamenco/features/fd_features_generated.c
Original file line number Diff line number Diff line change
Expand Up @@ -2365,6 +2365,13 @@ fd_feature_id_t const ids[] = {
.implemented = 1,
.cleaned_up = 0 },

{ .index = offsetof(fd_features_t, enforce_validator_location_registration)>>3,
.id = {"\x03\x88\x30\x50\xef\xa6\x06\xee\xcd\x5f\xba\x36\xf7\x57\xd7\xee\xb3\x71\x16\x40\xb2\x21\xc3\xc1\x29\x3e\x1e\x58\x55\x11\xaa\x80"},
/* EnforceVa1idatorLocat1onRegistrat1on1111111 */
.name = "enforce_validator_location_registration",
.implemented = 1,
.cleaned_up = 0 },

{ .index = ULONG_MAX }
};

Expand Down Expand Up @@ -2683,6 +2690,7 @@ typedef struct fd_feature_id_lookup_entry fd_feature_id_lookup_entry_t;
#define MAP_PERFECT_299 0x7b717607817b2451UL, .val = &ids[299]
#define MAP_PERFECT_300 0x0aa7b29de47f96cbUL, .val = &ids[300]
#define MAP_PERFECT_301 0xdbf2487401975107UL, .val = &ids[301]
#define MAP_PERFECT_302 0xee06a6ef50308803UL, .val = &ids[302]

#include "../../util/tmpl/fd_map_perfect.c"

Expand Down Expand Up @@ -2995,4 +3003,5 @@ FD_STATIC_ASSERT( offsetof( fd_features_t, vote_account_initialize_v2
FD_STATIC_ASSERT( offsetof( fd_features_t, raise_cpi_nesting_limit_to_8 )>>3==299UL, layout );
FD_STATIC_ASSERT( offsetof( fd_features_t, loader_v3_set_program_data_to_elf_length )>>3==300UL, layout );
FD_STATIC_ASSERT( offsetof( fd_features_t, validator_location_registration )>>3==301UL, layout );
FD_STATIC_ASSERT( offsetof( fd_features_t, enforce_validator_location_registration )>>3==302UL, layout );
FD_STATIC_ASSERT( sizeof( fd_features_t )>>3==FD_FEATURE_ID_CNT, layout );
5 changes: 3 additions & 2 deletions src/flamenco/features/fd_features_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
#endif

/* FEATURE_ID_CNT is the number of features in ids */
#define FD_FEATURE_ID_CNT (302UL)
#define FD_FEATURE_ID_CNT (303UL)

/* Feature set ID calculated from all feature names */
#define FD_FEATURE_SET_ID (3960938763U)
#define FD_FEATURE_SET_ID (3342991122U)

union fd_features {
ulong f[ FD_FEATURE_ID_CNT ];
Expand Down Expand Up @@ -318,5 +318,6 @@ union fd_features {
/* 0x7b717607817b2451 */ ulong raise_cpi_nesting_limit_to_8;
/* 0x0aa7b29de47f96cb */ ulong loader_v3_set_program_data_to_elf_length;
/* 0xdbf2487401975107 */ ulong validator_location_registration;
/* 0xee06a6ef50308803 */ ulong enforce_validator_location_registration;
};
};
3 changes: 2 additions & 1 deletion src/flamenco/features/feature_map.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,5 +300,6 @@
{"name":"vote_account_initialize_v2","implemented":0,"pubkey":"VoteAccount1nitia1izeV211111111111111111111"},
{"name":"raise_cpi_nesting_limit_to_8","implemented":0,"pubkey":"6TkHkRmP7JZy1fdM6fg5uXn76wChQBWGokHBJzrLB3mj"},
{"name":"loader_v3_set_program_data_to_elf_length","implemented":1,"pubkey":"EhisBfVtGvEA8bVCVN5VMaYEaX6iTfoUrmcDi8LY7Kxy"},
{"name":"validator_location_registration","implemented":1,"pubkey":"Va1idatorLocat1onRegistrat1on11111111111111","comment":"SIMD-0674, placeholder pubkey"}
{"name":"validator_location_registration","implemented":1,"pubkey":"Va1idatorLocat1onRegistrat1on11111111111111","comment":"SIMD-0674, placeholder pubkey"},
{"name":"enforce_validator_location_registration","implemented":1,"pubkey":"EnforceVa1idatorLocat1onRegistrat1on1111111","comment":"placeholder pubkey"}
]
99 changes: 98 additions & 1 deletion src/flamenco/runtime/test_vat_refresh_vote_accounts.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "../features/fd_features.h"
#include "../stakes/fd_stake_types.h"
#include "../stakes/fd_vote_stakes.h"
#include "../stakes/fd_stakes.h"

#include <sys/mman.h>
#include <unistd.h>
Expand All @@ -27,6 +28,7 @@
#define SENTINEL ((fd_accdb_fork_id_t){ .val = USHORT_MAX })

static fd_validator_location_t const LOC_FRA = { 4051542, 618526, 4870645 };
static fd_validator_location_t const * voter0_location = &LOC_FRA;

#define TEST_SLOTS_PER_EPOCH (12UL)
#define TEST_VAT_EPOCH (3UL)
Expand Down Expand Up @@ -187,12 +189,14 @@ put_vote_account_v4( test_env_t * env,
voter->prio = node_pubkey->uc[0];
fd_vote_authorized_voters_treap_ele_insert( vs->authorized_voters.treap, voter, vs->authorized_voters.pool );

if( voter0_is_v5 && fd_pubkey_eq( vote_account, &(fd_pubkey_t){ .ul[ 0 ] = 0x100UL } ) ) {
int v5 = voter0_is_v5 && fd_pubkey_eq( vote_account, &(fd_pubkey_t){ .ul[ 0 ] = 0x100UL } );
if( v5 ) {
FD_TEST( !fd_vsv_try_convert_to_v5( versioned, env->bank->f.epoch ) );
versioned->v5.location = LOC_FRA;
}

FD_TEST( !fd_vote_state_versioned_serialize( versioned, vote_state_data, sizeof(vote_state_data) ) );
if( v5 ) fd_vote_account_v5( vote_state_data )->location = *voter0_location;

fd_acc_t acc = fd_accdb_write_one( env->accdb, env->bank->accdb_fork_id, vote_account->uc );
acc.lamports = lamports;
Expand Down Expand Up @@ -270,6 +274,24 @@ enable_feature( test_env_t * env, ulong byte_offset, ulong activation_slot ) {
FD_LOG_ERR(( "feature id not found" ));
}

static void
enable_feature_pending( test_env_t * env, ulong byte_offset ) {
for( fd_feature_id_t const * id = fd_feature_iter_init(); !fd_feature_iter_done( id ); id = fd_feature_iter_next( id ) ) {
if( id->index != (byte_offset>>3) ) continue;
fd_feature_t feature = { .is_active = 0, .activation_slot = 0UL };
fd_acc_t acc = fd_accdb_write_one( env->accdb, env->bank->accdb_fork_id, id->id.uc );
acc.lamports = 1UL;
acc.executable = 0;
fd_memcpy( acc.owner, fd_solana_feature_program_id.key, sizeof(fd_pubkey_t) );
acc.data_len = sizeof(fd_feature_t);
fd_memcpy( acc.data, &feature, sizeof(fd_feature_t) );
acc.commit = 1;
fd_accdb_unwrite_one( env->accdb, &acc );
return;
}
FD_LOG_ERR(( "feature id not found" ));
}

/* Prep state for the upcoming epoch `for_epoch`, written into the
current (still un-rooted) slot so the next boundary refresh sees it:
- rewrite each voter's vote account (cached last vote -> first slot
Expand Down Expand Up @@ -621,6 +643,78 @@ test_vat_path_v5_voter( fd_wksp_t * wksp ) {
voter0_is_v5 = 0;
}

static void
test_enforce_registration_from_genesis( fd_wksp_t * wksp ) {
voter0_is_v5 = 1;
test_env_t env[1];
test_env_create( env, wksp );
enable_feature( env, offsetof( fd_features_t, enforce_validator_location_registration ), 0UL );

ulong const epoch = TEST_VAT_EPOCH-1UL;
advance_into_epoch( env, epoch );

FD_TEST( vote_stakes_t1_cnt( env->bank )==1UL );
for( ulong i=0UL; i<NUM_VOTERS; i++ ) {
fd_pubkey_t v = vote_key( i );
FD_TEST( fd_vote_stakes_query_t_1( fd_bank_vote_stakes( env->bank ), env->bank->vote_stakes_fork_id, &v, NULL )==( i==0UL ) );
}
FD_TEST( env->bank->f.total_epoch_stake==stake_for_epoch( 0UL, epoch ) );
FD_TEST( clock_delta( env )==CLOCK_DELTA_NO_WHALE );

test_env_destroy( env );
voter0_is_v5 = 0;
}

static void
test_enforce_registration_activates_at_boundary( fd_wksp_t * wksp ) {
voter0_is_v5 = 1;
test_env_t env[1];
test_env_create( env, wksp );

fd_pubkey_t v0 = vote_key( 0UL );
fd_pubkey_t v1 = vote_key( 1UL );

advance_into_epoch( env, 1UL );
FD_TEST( !FD_FEATURE_ACTIVE_BANK( env->bank, enforce_validator_location_registration ) );
FD_TEST( vote_stakes_t1_cnt( env->bank )==NUM_VAT_ELIGIBLE );
FD_TEST( fd_vote_stakes_query_t_1( fd_bank_vote_stakes( env->bank ), env->bank->vote_stakes_fork_id, &v1, NULL ) );

enable_feature_pending( env, offsetof( fd_features_t, enforce_validator_location_registration ) );
advance_into_epoch( env, 2UL );

FD_TEST( FD_FEATURE_ACTIVE_BANK( env->bank, enforce_validator_location_registration ) );
FD_TEST( env->bank->f.features.enforce_validator_location_registration==2UL*TEST_SLOTS_PER_EPOCH );
FD_TEST( vote_stakes_t1_cnt( env->bank )==1UL );
FD_TEST( fd_vote_stakes_query_t_1( fd_bank_vote_stakes( env->bank ), env->bank->vote_stakes_fork_id, &v0, NULL ) );
FD_TEST( !fd_vote_stakes_query_t_1( fd_bank_vote_stakes( env->bank ), env->bank->vote_stakes_fork_id, &v1, NULL ) );
FD_TEST( fd_vote_stakes_query_t_2( fd_bank_vote_stakes( env->bank ), env->bank->vote_stakes_fork_id, &v1, NULL ) );
FD_TEST( env->bank->f.total_epoch_stake==stake_for_epoch( 0UL, 2UL ) );

test_env_destroy( env );
voter0_is_v5 = 0;
}

static void
test_enforce_registration_v5_invalid_location( fd_wksp_t * wksp ) {
static fd_validator_location_t const in_bounds_invalid = { 6000000, 0, 0 };
voter0_is_v5 = 1;
voter0_location = &in_bounds_invalid;
test_env_t env[1];
test_env_create( env, wksp );

fd_pubkey_t v0 = vote_key( 0UL );
fd_acc_t ro = fd_accdb_read_one( env->accdb, env->bank->accdb_fork_id, v0.uc );
FD_TEST( FD_LOAD( uint, ro.data )==fd_vote_state_versioned_enum_v5 && FD_LOAD( int, ro.data+132 )==6000000 );
FD_TEST( fd_stakes_vote_account_is_admissible( env->bank, ro.lamports, ro.owner, ro.data, ro.data_len ) );
FD_FEATURE_SET_ACTIVE( &env->bank->f.features, enforce_validator_location_registration, 0UL );
FD_TEST( !fd_stakes_vote_account_is_admissible( env->bank, ro.lamports, ro.owner, ro.data, ro.data_len ) );
fd_accdb_unread_one( env->accdb, &ro );

test_env_destroy( env );
voter0_location = &LOC_FRA;
voter0_is_v5 = 0;
}

/* Whether the whale's last vote made it into the clock this epoch,
inferred from the stake-weighted timestamp: 10s when the dominant
future-voting whale is counted, 3s when it is not. */
Expand Down Expand Up @@ -731,6 +825,9 @@ main( int argc, char ** argv ) {
test_runtime_stack_stake_accum_map_sizing( wksp );
test_vat_path_unconditional( wksp );
test_vat_path_v5_voter( wksp );
test_enforce_registration_from_genesis( wksp );
test_enforce_registration_activates_at_boundary( wksp );
test_enforce_registration_v5_invalid_location( wksp );
test_vat_invalidate_revalidate( wksp );

fd_wksp_delete_anonymous( wksp );
Expand Down
4 changes: 3 additions & 1 deletion src/flamenco/stakes/fd_stakes.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,9 @@ fd_stakes_vote_account_is_admissible( fd_bank_t const * bank,
ulong minimum_balance = fd_rent_exempt_minimum_balance( &bank->f.rent, FD_VOTE_STATE_V4_SZ ) + vat_to_burn_per_epoch;
return lamports>=minimum_balance &&
fd_vsv_is_correct_size_owner_and_init( owner, data, data_len ) &&
fd_vote_account_has_bls_pubkey( data, data_len );
fd_vote_account_has_bls_pubkey( data, data_len ) &&
!( FD_FEATURE_ACTIVE_BANK( bank, enforce_validator_location_registration ) &&
!fd_vote_account_is_valid_v5( data, data_len ) );
}

void
Expand Down
Loading