Skip to content
Open
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
49 changes: 22 additions & 27 deletions src/discof/replay/fd_replay_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
34 changes: 10 additions & 24 deletions src/flamenco/runtime/fd_acc_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
18 changes: 2 additions & 16 deletions src/flamenco/runtime/fd_acc_mgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,39 +125,25 @@ 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).

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
Expand Down
21 changes: 4 additions & 17 deletions src/flamenco/runtime/fd_executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 3 additions & 9 deletions src/flamenco/runtime/fd_txn_account.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "fd_txn_account.h"
#include "fd_acc_mgr.h"
#include "fd_runtime.h"

void *
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 4 additions & 10 deletions src/flamenco/runtime/program/fd_system_program_nonce.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/runtime/tests/fd_harness_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
5 changes: 0 additions & 5 deletions src/funk/fd_funk_rec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion src/funk/fd_funk_rec.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading