diff --git a/src/discof/replay/fd_replay_tile.c b/src/discof/replay/fd_replay_tile.c index 677c6843d8c..679c4785737 100644 --- a/src/discof/replay/fd_replay_tile.c +++ b/src/discof/replay/fd_replay_tile.c @@ -477,38 +477,33 @@ fd_replay_out_vote_tower_from_funk( vote_tower_out->key = *pubkey; vote_tower_out->stake = stake; - /* Speculatively copy out the raw vote account state from Funk */ - for(;;) { - fd_memset( vote_tower_out->acc, 0, sizeof(vote_tower_out->acc) ); - - fd_funk_rec_query_t query; - fd_funk_rec_key_t funk_key = fd_funk_acc_key( pubkey ); - fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, xid, &funk_key, NULL, &query ); - if( FD_UNLIKELY( !rec ) ) { - FD_LOG_WARNING(( "vote account not found. address: %s", FD_BASE58_ENC_32_ALLOCA( pubkey->uc ) )); - return -1; - } - - uchar const * raw = fd_funk_val_const( rec, fd_funk_wksp(funk) ); - fd_account_meta_t const * metadata = fd_type_pun_const( raw ); + fd_memset( vote_tower_out->acc, 0, sizeof(vote_tower_out->acc) ); - ulong data_sz = metadata->dlen; - if( FD_UNLIKELY( data_sz > sizeof(vote_tower_out->acc) ) ) { - FD_LOG_WARNING(( "vote account %s has too large data. dlen %lu > %lu", - FD_BASE58_ENC_32_ALLOCA( pubkey->uc ), - data_sz, - sizeof(vote_tower_out->acc) )); - return -1; - } + fd_funk_rec_query_t query; + fd_funk_rec_key_t funk_key = fd_funk_acc_key( pubkey ); + fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, xid, &funk_key, NULL, &query ); + if( FD_UNLIKELY( !rec ) ) { + FD_LOG_WARNING(( "vote account not found. address: %s", FD_BASE58_ENC_32_ALLOCA( pubkey->uc ) )); + return -1; + } - fd_memcpy( vote_tower_out->acc, raw + sizeof(fd_account_meta_t), data_sz ); - vote_tower_out->acc_sz = data_sz; + uchar const * raw = fd_funk_val_const( rec, fd_funk_wksp(funk) ); + fd_account_meta_t const * metadata = fd_type_pun_const( raw ); - if( FD_LIKELY( fd_funk_rec_query_test( &query ) == FD_FUNK_SUCCESS ) ) { - break; - } + ulong data_sz = metadata->dlen; + if( FD_UNLIKELY( data_sz > sizeof(vote_tower_out->acc) ) ) { + FD_LOG_WARNING(( "vote account %s has too large data. dlen %lu > %lu", + FD_BASE58_ENC_32_ALLOCA( pubkey->uc ), + data_sz, + sizeof(vote_tower_out->acc) )); + return -1; } + fd_memcpy( vote_tower_out->acc, raw + sizeof(fd_account_meta_t), data_sz ); + vote_tower_out->acc_sz = data_sz; + + FD_TEST( fd_funk_rec_query_test( &query )==FD_FUNK_SUCCESS ); + return 0; } diff --git a/src/flamenco/runtime/fd_acc_mgr.c b/src/flamenco/runtime/fd_acc_mgr.c index 793839db365..7b3c6df2380 100644 --- a/src/flamenco/runtime/fd_acc_mgr.c +++ b/src/flamenco/runtime/fd_acc_mgr.c @@ -5,41 +5,27 @@ fd_account_meta_t const * fd_funk_get_acc_meta_readonly( fd_funk_t const * funk, fd_funk_txn_xid_t const * xid, - fd_pubkey_t const * pubkey, - fd_funk_rec_t const ** orec, - int * opt_err, - fd_funk_txn_t const ** txn_out ) { + fd_pubkey_t const * pubkey ) { fd_funk_rec_key_t id = fd_funk_acc_key( pubkey ); /* When we access this pointer later on in the execution pipeline, we assume that nothing else will change that account. If the account is writable in the solana txn, then we copy the data. If the account is read-only, we do not. This is safe because of the read-write locks that the solana transaction holds on the account. */ - for( ; ; ) { - fd_funk_rec_query_t query[1]; - fd_funk_txn_t const * dummy_txn_out[1]; - if( !txn_out ) txn_out = dummy_txn_out; - fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, xid, &id, txn_out, query ); - - if( FD_UNLIKELY( !rec || !!( rec->flags & FD_FUNK_REC_FLAG_ERASE ) ) ) { - fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT ); - return NULL; - } - if( NULL != orec ) - *orec = rec; + fd_funk_rec_query_t query[1]; + fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, xid, &id, NULL, query ); - void const * raw = fd_funk_val( rec, fd_funk_wksp(funk) ); + if( FD_UNLIKELY( !rec || !!( rec->flags & FD_FUNK_REC_FLAG_ERASE ) ) ) { + return NULL; + } - fd_account_meta_t const * metadata = fd_type_pun_const( raw ); - if( FD_LIKELY( fd_funk_rec_query_test( query ) == FD_FUNK_SUCCESS ) ) { - return metadata; - } + void const * raw = fd_funk_val( rec, fd_funk_wksp(funk) ); - } + fd_account_meta_t const * metadata = fd_type_pun_const( raw ); + FD_TEST( fd_funk_rec_query_test( query )==FD_FUNK_SUCCESS ); - /* unreachable */ - return NULL; + return metadata; } fd_account_meta_t * diff --git a/src/flamenco/runtime/fd_acc_mgr.h b/src/flamenco/runtime/fd_acc_mgr.h index 48682755d5f..56fa4c338f3 100644 --- a/src/flamenco/runtime/fd_acc_mgr.h +++ b/src/flamenco/runtime/fd_acc_mgr.h @@ -125,9 +125,6 @@ fd_funk_key_is_acc( fd_funk_rec_key_t const * id ) { On success: - loads the account data into in-memory cache - returns a pointer to it in the caller's local address space - - if out_rec!=NULL, sets *out_rec to a pointer to the funk rec. - This handle is suitable as opt_con_rec for fd_funk_get_acc_meta_readonly. - - notably, leaves *opt_err untouched, even if opt_err!=NULL First byte of returned pointer is first byte of fd_account_meta_t. To find data region of account, add sizeof(fd_account_meta_t). @@ -135,29 +132,18 @@ fd_funk_key_is_acc( fd_funk_rec_key_t const * id ) { Lifetime of returned fd_funk_rec_t and account record pointers ends when user calls modify_data for same account, or tranasction ends. - On failure, returns NULL, and sets *opt_err if opt_err!=NULL. - Reasons for error include - - account not found - - internal database or user error (out of memory, attempting to view - record which has an active modify_data handle, etc.) + If the account was not found returns NULL. It is always wrong to cast return value to a non-const pointer. Instead, use fd_funk_get_acc_meta_mutable to acquire a mutable handle. - if txn_out is supplied (non-null), the txn the key was found in - is returned. If *txn_out == NULL, the key was found in the root - context. - IMPORTANT: fd_funk_get_acc_meta_readonly is only safe if it is guaranteed there are no other modifying accesses to the account. */ fd_account_meta_t const * fd_funk_get_acc_meta_readonly( fd_funk_t const * funk, fd_funk_txn_xid_t const * xid, - fd_pubkey_t const * pubkey, - fd_funk_rec_t const ** orec, - int * opt_err, - fd_funk_txn_t const ** txn_out ) ; + fd_pubkey_t const * pubkey ) ; /* fd_funk_get_acc_meta_mutable requests a writable handle to an account. Follows interface of fd_funk_get_account_meta_readonly with the following diff --git a/src/flamenco/runtime/fd_executor.c b/src/flamenco/runtime/fd_executor.c index 9b0afcf0486..5e2d4a7f6a0 100644 --- a/src/flamenco/runtime/fd_executor.c +++ b/src/flamenco/runtime/fd_executor.c @@ -940,14 +940,11 @@ fd_executor_create_rollback_fee_payer_account( fd_exec_txn_ctx_t * txn_ctx, if( FD_UNLIKELY( txn_ctx->nonce_account_idx_in_txn==FD_FEE_PAYER_TXN_IDX ) ) { rollback_fee_payer_acc = txn_ctx->rollback_nonce_account; } else { - int err = FD_ACC_MGR_SUCCESS; fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly( txn_ctx->funk, txn_ctx->xid, - fee_payer_key, - NULL, - &err, - NULL ); + fee_payer_key ); + if( FD_UNLIKELY( !meta ) ) FD_LOG_CRIT(( "Missing fee payer account %s", FD_BASE58_ENC_32_ALLOCA( fee_payer_key->key ) )); ulong data_len = fd_txn_account_get_data_len( &txn_ctx->accounts[FD_FEE_PAYER_TXN_IDX] ); void * fee_payer_data = fd_spad_alloc( txn_ctx->spad, FD_ACCOUNT_REC_ALIGN, sizeof(fd_account_meta_t) + data_len ); @@ -1401,23 +1398,13 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx, fd_pubkey_t * acc = &txn_ctx->account_keys[ idx ]; - int err = FD_ACC_MGR_SUCCESS; fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly( txn_ctx->funk, txn_ctx->xid, - acc, - NULL, - &err, - NULL ); + acc ); fd_txn_account_t * txn_account = &txn_ctx->accounts[ idx ]; - /* If there is an error with a read from the accounts database, it is - unexpected unless the account does not exist. */ - if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS && err!=FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT ) ) { - FD_LOG_CRIT(( "fd_txn_account_init_from_funk_readonly err=%d", err )); - } - int is_writable = fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, idx ) || idx==FD_FEE_PAYER_TXN_IDX; fd_account_meta_t * account_meta = NULL; fd_wksp_t * data_wksp = NULL; @@ -1448,7 +1435,7 @@ fd_executor_setup_txn_account( fd_exec_txn_ctx_t * txn_ctx, if the account does not exist, we need to initialize a new metadata. */ - if( FD_LIKELY( err==FD_ACC_MGR_SUCCESS ) ) { + if( FD_LIKELY( meta ) ) { account_meta = (fd_account_meta_t *)meta; data_wksp = fd_funk_wksp( txn_ctx->funk ); } else { diff --git a/src/flamenco/runtime/fd_txn_account.c b/src/flamenco/runtime/fd_txn_account.c index 4569df61492..de56fbecc13 100644 --- a/src/flamenco/runtime/fd_txn_account.c +++ b/src/flamenco/runtime/fd_txn_account.c @@ -1,4 +1,5 @@ #include "fd_txn_account.h" +#include "fd_acc_mgr.h" #include "fd_runtime.h" void * @@ -153,18 +154,11 @@ fd_txn_account_init_from_funk_readonly( fd_txn_account_t * acct, fd_funk_t const * funk, fd_funk_txn_xid_t const * xid ) { - int err = FD_ACC_MGR_SUCCESS; fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly( funk, xid, - pubkey, - NULL, - &err, - NULL ); - - if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) { - return err; - } + pubkey ); + if( FD_UNLIKELY( !meta ) ) return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT; if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new( acct, diff --git a/src/flamenco/runtime/program/fd_system_program_nonce.c b/src/flamenco/runtime/program/fd_system_program_nonce.c index 156160874a4..ea9c1108e9c 100644 --- a/src/flamenco/runtime/program/fd_system_program_nonce.c +++ b/src/flamenco/runtime/program/fd_system_program_nonce.c @@ -994,15 +994,12 @@ fd_check_transaction_age( fd_exec_txn_ctx_t * txn_ctx ) { fd_account_meta_t const * meta = fd_funk_get_acc_meta_readonly( txn_ctx->funk, txn_ctx->xid, - &txn_ctx->account_keys[ instr_accts[ 0UL ] ], - NULL, - &err, - NULL ); - ulong acc_data_len = meta->dlen; - - if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) { + &txn_ctx->account_keys[ instr_accts[ 0UL ] ] ); + if( FD_UNLIKELY( !meta ) ) { return FD_RUNTIME_TXN_ERR_BLOCKHASH_NOT_FOUND; } + + ulong acc_data_len = meta->dlen; fd_nonce_state_versions_t new_state = { .discriminant = fd_nonce_state_versions_enum_current, .inner = { .current = { @@ -1025,9 +1022,6 @@ fd_check_transaction_age( fd_exec_txn_ctx_t * txn_ctx ) { if( FD_UNLIKELY( !borrowed_account_data ) ) { FD_LOG_CRIT(( "Failed to allocate memory for nonce account" )); } - if( FD_UNLIKELY( !meta ) ) { - FD_LOG_CRIT(( "Failed to get meta for nonce account" )); - } fd_memcpy( borrowed_account_data, meta, sizeof(fd_account_meta_t)+acc_data_len ); if( FD_UNLIKELY( !fd_txn_account_join( fd_txn_account_new( diff --git a/src/flamenco/runtime/tests/fd_harness_common.c b/src/flamenco/runtime/tests/fd_harness_common.c index 159c6c99bef..0d1fbb558ad 100644 --- a/src/flamenco/runtime/tests/fd_harness_common.c +++ b/src/flamenco/runtime/tests/fd_harness_common.c @@ -20,7 +20,7 @@ fd_runtime_fuzz_load_account( fd_txn_account_t * acc, fd_pubkey_t pubkey[1]; memcpy( pubkey, state->address, sizeof(fd_pubkey_t) ); /* Account must not yet exist */ - if( FD_UNLIKELY( fd_funk_get_acc_meta_readonly( funk, xid, pubkey, NULL, NULL, NULL) ) ) { + if( FD_UNLIKELY( fd_funk_get_acc_meta_readonly( funk, xid, pubkey ) ) ) { return 0; } diff --git a/src/funk/fd_funk_rec.c b/src/funk/fd_funk_rec.c index b13982f3ad0..4311a7b612a 100644 --- a/src/funk/fd_funk_rec.c +++ b/src/funk/fd_funk_rec.c @@ -226,11 +226,6 @@ fd_funk_rec_query_copy( fd_funk_t * funk, } } -int -fd_funk_rec_query_test( fd_funk_rec_query_t * query ) { - return fd_funk_rec_map_query_test( query ); -} - fd_funk_rec_t * fd_funk_rec_prepare( fd_funk_t * funk, fd_funk_txn_xid_t const * xid, diff --git a/src/funk/fd_funk_rec.h b/src/funk/fd_funk_rec.h index b673a1c6c65..19bc2aaa030 100644 --- a/src/funk/fd_funk_rec.h +++ b/src/funk/fd_funk_rec.h @@ -225,7 +225,10 @@ fd_funk_rec_query_try( fd_funk_t * funk, } */ -int fd_funk_rec_query_test( fd_funk_rec_query_t * query ); +static inline int +fd_funk_rec_query_test( fd_funk_rec_query_t * query ) { + return fd_funk_rec_map_query_test( query ); +} /* fd_funk_rec_query_try_global is the same as fd_funk_rec_query_try but will query txn's ancestors for key from youngest to oldest if key is