Skip to content

Commit c8b03c6

Browse files
add condition filtering for txn ctx account getters
1 parent 3257f0c commit c8b03c6

9 files changed

+81
-29
lines changed

src/flamenco/runtime/context/fd_exec_instr_ctx.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ fd_exec_instr_ctx_try_borrow_last_program_account( fd_exec_instr_ctx_t const * c
147147
fd_txn_account_t * program_account = NULL;
148148
fd_exec_txn_ctx_get_account_at_index( ctx->txn_ctx,
149149
ctx->instr->program_id,
150-
&program_account );
150+
&program_account,
151+
NULL );
151152

152153
return fd_exec_instr_ctx_try_borrow_account( ctx,
153154
ctx->instr->program_id,

src/flamenco/runtime/context/fd_exec_instr_ctx.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct __attribute__((aligned(8UL))) fd_exec_instr_ctx {
4141
/* Be careful when using this macro. There may be places where the error
4242
will need to be handled differently. */
4343
#define FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, idx, acc ) do { \
44-
int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, idx, acc ); \
44+
int err = fd_exec_instr_ctx_try_borrow_instr_account( ctx, idx, acc ); \
4545
if( FD_UNLIKELY( err ) ) return err; \
4646
} while (0)
4747

src/flamenco/runtime/context/fd_exec_txn_ctx.c

+26-7
Original file line numberDiff line numberDiff line change
@@ -86,39 +86,56 @@ fd_exec_txn_ctx_delete( void * mem ) {
8686
int
8787
fd_exec_txn_ctx_get_account_at_index( fd_exec_txn_ctx_t * ctx,
8888
uchar idx,
89-
fd_txn_account_t * * account ) {
89+
fd_txn_account_t * * account,
90+
int (*condition)( fd_exec_txn_ctx_t * ctx,
91+
int idx,
92+
fd_txn_account_t * acc) ) {
9093
if( FD_UNLIKELY( idx>=ctx->accounts_cnt ) ) {
9194
return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
9295
}
9396

9497
fd_txn_account_t * txn_account = &ctx->accounts[idx];
9598
*account = txn_account;
9699

100+
if( condition != NULL ) {
101+
if( FD_UNLIKELY( !condition( ctx, idx, *account ) ) )
102+
return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
103+
}
104+
97105
return FD_ACC_MGR_SUCCESS;
98106
}
99107

100108
int
101109
fd_exec_txn_ctx_get_account_with_key( fd_exec_txn_ctx_t * ctx,
102110
fd_pubkey_t const * pubkey,
103-
fd_txn_account_t * * account ) {
111+
fd_txn_account_t * * account,
112+
int (*condition)( fd_exec_txn_ctx_t * ctx,
113+
int idx,
114+
fd_txn_account_t * acc) ) {
104115
int index = fd_exec_txn_ctx_find_index_of_account( ctx, pubkey );
105116
if( FD_UNLIKELY( index==-1 ) ) {
106117
return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
107118
}
108119

109-
return fd_exec_txn_ctx_get_account_at_index( ctx, (uchar)index, account );
120+
return fd_exec_txn_ctx_get_account_at_index( ctx,
121+
(uchar)index,
122+
account,
123+
condition );
110124
}
111125

112126
int
113127
fd_exec_txn_ctx_get_executable_account( fd_exec_txn_ctx_t * ctx,
114128
fd_pubkey_t const * pubkey,
115-
fd_txn_account_t * * account ) {
129+
fd_txn_account_t * * account,
130+
int (*condition)( fd_exec_txn_ctx_t * ctx,
131+
int idx,
132+
fd_txn_account_t * acc) ) {
116133
/* First try to fetch the executable account from the existing borrowed accounts.
117134
If the pubkey is in the account keys, then we want to re-use that
118135
borrowed account since it reflects changes from prior instructions. Referencing the
119136
read-only executable accounts list is incorrect behavior when the program
120137
data account is written to in a prior instruction (e.g. program upgrade + invoke within the same txn) */
121-
int err = fd_exec_txn_ctx_get_account_with_key( ctx, pubkey, account );
138+
int err = fd_exec_txn_ctx_get_account_with_key( ctx, pubkey, account, condition );
122139
if( FD_UNLIKELY( err==FD_ACC_MGR_SUCCESS ) ) {
123140
return FD_ACC_MGR_SUCCESS;
124141
}
@@ -128,8 +145,10 @@ fd_exec_txn_ctx_get_executable_account( fd_exec_txn_ctx_t * ctx,
128145
fd_txn_account_t * txn_account = &ctx->executable_accounts[i];
129146
*account = txn_account;
130147

131-
if( FD_UNLIKELY( !fd_acc_exists( txn_account->const_meta ) ) )
132-
return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
148+
if( condition != NULL ) {
149+
if( FD_UNLIKELY( !condition( ctx, (int)i, *account ) ) )
150+
return FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT;
151+
}
133152

134153
return FD_ACC_MGR_SUCCESS;
135154
}

src/flamenco/runtime/context/fd_exec_txn_ctx.h

+39-4
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ fd_exec_txn_ctx_find_index_of_account( fd_exec_txn_ctx_t * ctx,
240240
fd_pubkey_t const * pubkey ) {
241241
for( ulong i=ctx->accounts_cnt; i>0UL; i-- ) {
242242
if( 0==memcmp( pubkey, &ctx->account_keys[ i-1UL ], sizeof(fd_pubkey_t) ) ) {
243-
return (int)((ushort)i);
243+
return (int)(i-1UL);
244244
}
245245
}
246246
return -1;
@@ -253,17 +253,26 @@ fd_exec_txn_ctx_find_index_of_account( fd_exec_txn_ctx_t * ctx,
253253
int
254254
fd_exec_txn_ctx_get_account_at_index( fd_exec_txn_ctx_t * ctx,
255255
uchar idx,
256-
fd_txn_account_t * * account );
256+
fd_txn_account_t * * account,
257+
int (*condition)( fd_exec_txn_ctx_t * ctx,
258+
int idx,
259+
fd_txn_account_t * acc) );
257260

258261
int
259262
fd_exec_txn_ctx_get_account_with_key( fd_exec_txn_ctx_t * ctx,
260263
fd_pubkey_t const * pubkey,
261-
fd_txn_account_t * * account );
264+
fd_txn_account_t * * account,
265+
int (*condition)( fd_exec_txn_ctx_t * ctx,
266+
int idx,
267+
fd_txn_account_t * acc) );
262268

263269
int
264270
fd_exec_txn_ctx_get_executable_account( fd_exec_txn_ctx_t * ctx,
265271
fd_pubkey_t const * pubkey,
266-
fd_txn_account_t * * account );
272+
fd_txn_account_t * * account,
273+
int (*condition)( fd_exec_txn_ctx_t * ctx,
274+
int idx,
275+
fd_txn_account_t * acc) );
267276

268277
void
269278
fd_exec_txn_ctx_reset_return_data( fd_exec_txn_ctx_t * txn_ctx );
@@ -283,6 +292,32 @@ fd_exec_txn_ctx_reset_return_data( fd_exec_txn_ctx_t * txn_ctx );
283292
int
284293
fd_exec_txn_ctx_account_is_writable_idx( fd_exec_txn_ctx_t const * txn_ctx, int idx );
285294

295+
/* Conditional filter functions */
296+
static inline int
297+
fd_txn_account_exists( fd_exec_txn_ctx_t * ctx,
298+
int idx,
299+
fd_txn_account_t * acc ) {
300+
(void) ctx;
301+
(void) idx;
302+
return fd_acc_exists( acc->const_meta );
303+
}
304+
305+
static inline int
306+
fd_txn_account_is_writable( fd_exec_txn_ctx_t * ctx,
307+
int idx,
308+
fd_txn_account_t * acc ) {
309+
(void) acc;
310+
return fd_exec_txn_ctx_account_is_writable_idx( ctx, idx );
311+
}
312+
313+
static inline int
314+
fd_txn_account_fee_payer_writable( fd_exec_txn_ctx_t * ctx,
315+
int idx,
316+
fd_txn_account_t * acc ) {
317+
(void) acc;
318+
return fd_txn_is_writable( ctx->txn_descriptor, idx );
319+
}
320+
286321
FD_PROTOTYPES_END
287322

288323
#endif /* HEADER_fd_src_flamenco_runtime_context_fd_exec_txn_ctx_h */

src/flamenco/runtime/fd_executor.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ fd_executor_load_transaction_accounts( fd_exec_txn_ctx_t * txn_ctx ) {
444444
/* https://github.com/anza-xyz/agave/blob/v2.2.0/svm/src/account_loader.rs#L429-L443 */
445445
for( ulong i=0UL; i<txn_ctx->accounts_cnt; i++ ) {
446446
fd_txn_account_t * acct = &txn_ctx->accounts[i];
447-
uchar unknown_acc = !!( fd_exec_txn_ctx_get_account_at_index( txn_ctx, (uchar)i, &acct ) ||
447+
uchar unknown_acc = !!( fd_exec_txn_ctx_get_account_at_index( txn_ctx, (uchar)i, &acct, &fd_txn_account_exists ) ||
448448
acct->const_meta->info.lamports==0UL );
449449
ulong acc_size = unknown_acc ? 0UL : acct->const_meta->dlen;
450450
uchar is_writable = !!( fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, (int)i ) );
@@ -493,7 +493,7 @@ fd_executor_load_transaction_accounts( fd_exec_txn_ctx_t * txn_ctx ) {
493493
/* Mimicking `load_account()` here with 0-lamport check as well.
494494
https://github.com/anza-xyz/agave/blob/v2.2.0/svm/src/account_loader.rs#L455-L462 */
495495
fd_txn_account_t * program_account = NULL;
496-
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, instr->program_id, &program_account );
496+
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, instr->program_id, &program_account, &fd_txn_account_exists );
497497
if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS || program_account->const_meta->info.lamports==0UL ) ) {
498498
return FD_RUNTIME_TXN_ERR_PROGRAM_ACCOUNT_NOT_FOUND;
499499
}
@@ -792,8 +792,8 @@ fd_executor_validate_transaction_fee_payer( fd_exec_txn_ctx_t * txn_ctx ) {
792792
doesn't have a writable signature.
793793
https://github.com/anza-xyz/agave/blob/16de8b75ebcd57022409b422de557dd37b1de8db/svm/src/transaction_processor.rs#L431-L436 */
794794
fd_txn_account_t * fee_payer_rec = NULL;
795-
err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, FD_FEE_PAYER_TXN_IDX, &fee_payer_rec );
796-
if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS || !fd_txn_is_writable( txn_ctx->txn_descriptor, FD_FEE_PAYER_TXN_IDX ) ) ) {
795+
err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, FD_FEE_PAYER_TXN_IDX, &fee_payer_rec, &fd_txn_account_fee_payer_writable );
796+
if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
797797
return FD_RUNTIME_TXN_ERR_ACCOUNT_NOT_FOUND;
798798
}
799799

src/flamenco/runtime/program/fd_bpf_loader_program.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ read_bpf_upgradeable_loader_state_for_program( fd_exec_txn_ctx_t *
130130
uchar program_id,
131131
int * opt_err ) {
132132
fd_txn_account_t * rec = NULL;
133-
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, program_id, &rec );
133+
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, program_id, &rec, &fd_txn_account_exists );
134134
if( FD_UNLIKELY( err ) ) {
135135
*opt_err = err;
136136
return NULL;
@@ -1923,7 +1923,7 @@ fd_bpf_loader_program_execute( fd_exec_instr_ctx_t * ctx ) {
19231923

19241924
fd_txn_account_t * program_data_account = NULL;
19251925
fd_pubkey_t * programdata_pubkey = (fd_pubkey_t *)&program_account_state->inner.program.programdata_address;
1926-
err = fd_exec_txn_ctx_get_executable_account( ctx->txn_ctx, programdata_pubkey, &program_data_account );
1926+
err = fd_exec_txn_ctx_get_executable_account( ctx->txn_ctx, programdata_pubkey, &program_data_account, &fd_txn_account_exists );
19271927
if( FD_UNLIKELY( err!=FD_ACC_MGR_SUCCESS ) ) {
19281928
return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
19291929
}

src/flamenco/runtime/program/fd_loader_v4_program.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ fd_loader_v4_program_execute( fd_exec_instr_ctx_t * instr_ctx ) {
777777
/* try borrow last program account */
778778
/* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/loader-v4/src/lib.rs#L489 */
779779
fd_txn_account_t * program = NULL;
780-
rc = fd_exec_txn_ctx_get_account_at_index( instr_ctx->txn_ctx, instr_ctx->instr->program_id, &program );
780+
rc = fd_exec_txn_ctx_get_account_at_index( instr_ctx->txn_ctx, instr_ctx->instr->program_id, &program, &fd_txn_account_exists );
781781
if( FD_UNLIKELY( rc ) ) {
782782
return rc;
783783
}

src/flamenco/runtime/sysvar/fd_sysvar_instructions.c

+3-7
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fd_sysvar_instructions_serialize_account( fd_exec_txn_ctx_t * txn_ctx,
3939
ulong serialized_sz = instructions_serialized_size( instrs, instrs_cnt );
4040

4141
fd_txn_account_t * rec = NULL;
42-
int err = fd_exec_txn_ctx_get_account_with_key( txn_ctx, &fd_sysvar_instructions_id, &rec );
42+
int err = fd_exec_txn_ctx_get_account_with_key( txn_ctx, &fd_sysvar_instructions_id, &rec, &fd_txn_account_exists );
4343
if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS && rec == NULL ) ) {
4444
/* The way we use this, this should NEVER hit since the borrowed accounts should be set up
4545
before this is called, and this is only called if the sysvar instructions account is in
@@ -139,13 +139,9 @@ fd_sysvar_instructions_update_current_instr_idx( fd_exec_txn_ctx_t * txn_ctx,
139139
}
140140

141141
/* https://github.com/anza-xyz/agave/blob/v2.1.14/svm/src/message_processor.rs#L53-L55 */
142-
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, (uchar)index, &rec );
143-
if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) )
142+
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx, (uchar)index, &rec, NULL );
143+
if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) ) {
144144
return FD_ACC_MGR_ERR_READ_FAILED;
145-
146-
/* Check if account is writable */
147-
if( FD_UNLIKELY( !fd_exec_txn_ctx_account_is_writable_idx( txn_ctx, index ) ) ) {
148-
return FD_ACC_MGR_ERR_WRITE_FAILED;
149145
}
150146

151147
/* Store the current instruction index

src/flamenco/runtime/tests/fd_exec_instr_test.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -2290,7 +2290,7 @@ __wrap_fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx,
22902290
TODO: Once direct mapping is enabled we _technically_ don't need
22912291
this check */
22922292

2293-
if( fd_exec_txn_ctx_get_account_at_index( txn_ctx, idx_in_txn, &acct ) ) {
2293+
if( fd_exec_txn_ctx_get_account_at_index( txn_ctx, idx_in_txn, &acct, &fd_txn_account_exists ) ) {
22942294
break;
22952295
}
22962296
if( acct->meta == NULL ){
@@ -2301,7 +2301,8 @@ __wrap_fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx,
23012301
int err = fd_exec_txn_ctx_get_account_at_index( txn_ctx,
23022302
idx_in_txn,
23032303
/* Do not reallocate if data is not going to be modified */
2304-
&acct );
2304+
&acct,
2305+
&fd_txn_account_is_writable );
23052306
if( err ) break;
23062307

23072308
/* resize manually */

0 commit comments

Comments
 (0)