Skip to content

Commit 7b4ccd0

Browse files
committed
flamenco, program-cache: remove end-of-slot iterations
1 parent fb1b599 commit 7b4ccd0

22 files changed

+1390
-845
lines changed

src/flamenco/runtime/context/fd_exec_txn_ctx.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ fd_exec_txn_ctx_setup_basic( fd_exec_txn_ctx_t * ctx ) {
180180
ctx->instr_stack_sz = 0;
181181
ctx->accounts_cnt = 0UL;
182182
ctx->executable_cnt = 0UL;
183+
ctx->programs_to_reverify_cnt = 0UL;
184+
183185
ctx->paid_fees = 0UL;
184186
ctx->loaded_accounts_data_size = 0UL;
185187
ctx->accounts_resize_delta = 0UL;

src/flamenco/runtime/context/fd_exec_txn_ctx.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,15 @@ struct fd_exec_txn_ctx {
106106
fd_txn_account_t executable_accounts[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of BPF upgradeable loader program data accounts */
107107
fd_txn_account_t accounts[ MAX_TX_ACCOUNT_LOCKS ]; /* Array of borrowed accounts accessed by this transaction. */
108108

109+
/* When a program is deployed or upgraded, we must queue it to be
110+
updated in the program cache (if it exists already) so that
111+
the cache entry's ELF / sBPF information can be updated for future
112+
executions. We keep an array of pubkeys for the transaction to
113+
track which programs need to be reverified. The actual queueing
114+
for reverification is done in the transaction finalization step. */
115+
uchar programs_to_reverify_cnt;
116+
fd_pubkey_t programs_to_reverify[ MAX_TX_ACCOUNT_LOCKS ];
117+
109118
/* The next three fields describe Agave's "rollback" accounts, which
110119
are copies of the fee payer and (if applicable) nonce account. If the
111120
transaction fails to load, the fee payer is still debited the transaction fee,

src/flamenco/runtime/fd_executor.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "program/fd_vote_program.h"
2121
#include "program/fd_zk_elgamal_proof_program.h"
2222
#include "sysvar/fd_sysvar_cache.h"
23+
#include "program/fd_program_cache.h"
2324
#include "sysvar/fd_sysvar_epoch_schedule.h"
2425
#include "sysvar/fd_sysvar_instructions.h"
2526
#include "sysvar/fd_sysvar_rent.h"

src/flamenco/runtime/fd_runtime.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "program/fd_stake_program.h"
2626
#include "program/fd_builtin_programs.h"
2727
#include "program/fd_vote_program.h"
28-
#include "program/fd_bpf_program_util.h"
28+
#include "program/fd_program_cache.h"
2929
#include "program/fd_bpf_loader_program.h"
3030
#include "program/fd_address_lookup_table_program.h"
3131

@@ -1027,12 +1027,6 @@ fd_runtime_block_execute_finalize_start( fd_exec_slot_ctx_t * slot_c
10271027
/* This slot is now "frozen" and can't be changed anymore. */
10281028
fd_runtime_freeze( slot_ctx );
10291029

1030-
int result = fd_bpf_scan_and_create_bpf_program_cache_entry( slot_ctx, runtime_spad );
1031-
if( FD_UNLIKELY( result ) ) {
1032-
FD_LOG_WARNING(( "update bpf program cache failed" ));
1033-
return;
1034-
}
1035-
10361030
/* Collect list of changed accounts to be added to bank hash */
10371031
*task_data = fd_spad_alloc( runtime_spad,
10381032
alignof(fd_accounts_hash_task_data_t),
@@ -1390,6 +1384,16 @@ fd_runtime_finalize_txn( fd_funk_t * funk,
13901384

13911385
fd_txn_account_save( &txn_ctx->accounts[i], funk, funk_txn, txn_ctx->spad_wksp );
13921386
}
1387+
1388+
/* We need to queue any existing program accounts that may have
1389+
been deployed / upgraded for reverification in the program
1390+
cache since their programdata may have changed. ELF / sBPF
1391+
metadata will need to be updated. */
1392+
ulong current_slot = fd_bank_slot_get( bank );
1393+
for( uchar i=0; i<txn_ctx->programs_to_reverify_cnt; i++ ) {
1394+
fd_pubkey_t const * program_key = &txn_ctx->programs_to_reverify[i];
1395+
fd_program_cache_queue_program_for_reverification( funk, funk_txn, program_key, current_slot );
1396+
}
13931397
}
13941398

13951399
int is_vote = fd_txn_is_simple_vote_transaction( txn_ctx->txn_descriptor, txn_ctx->_txn_raw->raw );
@@ -1889,6 +1893,7 @@ fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
18891893
/* Deploy the new target Core BPF program.
18901894
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L268-L271 */
18911895
err = fd_directly_invoke_loader_v3_deploy( slot_ctx,
1896+
builtin_program_id,
18921897
new_target_program_data_account->vt->get_data( new_target_program_data_account ) + PROGRAMDATA_METADATA_SIZE,
18931898
new_target_program_data_account->vt->get_data_len( new_target_program_data_account ) - PROGRAMDATA_METADATA_SIZE,
18941899
runtime_spad );
@@ -2222,7 +2227,7 @@ fd_runtime_update_program_cache( fd_exec_slot_ctx_t * slot_ctx,
22222227
fd_acct_addr_t const * acc_addrs = fd_txn_get_acct_addrs( txn_descriptor, txn_p );
22232228
for( ushort acc_idx=0; acc_idx<txn_descriptor->acct_addr_cnt; acc_idx++ ) {
22242229
fd_pubkey_t const * account = fd_type_pun_const( &acc_addrs[acc_idx] );
2225-
fd_bpf_program_update_program_cache( slot_ctx, account, runtime_spad );
2230+
fd_program_cache_update_program( slot_ctx, account, runtime_spad );
22262231
}
22272232

22282233
if( txn_descriptor->transaction_version==FD_TXN_V0 ) {
@@ -2236,6 +2241,11 @@ fd_runtime_update_program_cache( fd_exec_slot_ctx_t * slot_ctx,
22362241

22372242
fd_slot_hash_t * slot_hash = deq_fd_slot_hash_t_join( (uchar *)slot_hashes_global + slot_hashes_global->hashes_offset );
22382243

2244+
/* TODO: This is done twice, once in the replay tile and once in the
2245+
exec tile. We should consolidate the account resolution into a
2246+
single place, but also keep in mind from a conformance
2247+
perspective that these ALUT resolution checks happen after some
2248+
things like compute budget instruction parsing */
22392249
if( FD_UNLIKELY( fd_runtime_load_txn_address_lookup_tables(
22402250
txn_descriptor,
22412251
txn_p->payload,
@@ -2249,7 +2259,7 @@ fd_runtime_update_program_cache( fd_exec_slot_ctx_t * slot_ctx,
22492259

22502260
for( ushort alut_idx=0; alut_idx<txn_descriptor->addr_table_adtl_cnt; alut_idx++ ) {
22512261
fd_pubkey_t const * account = fd_type_pun_const( &alut_accounts[alut_idx] );
2252-
fd_bpf_program_update_program_cache( slot_ctx, account, runtime_spad );
2262+
fd_program_cache_update_program( slot_ctx, account, runtime_spad );
22532263
}
22542264
}
22552265

src/flamenco/runtime/fd_runtime.h

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -619,21 +619,15 @@ fd_runtime_block_pre_execute_process_new_epoch( fd_exec_slot_ctx_t * slot_ctx,
619619
fd_spad_t * runtime_spad,
620620
int * is_epoch_boundary );
621621

622-
/* This function is responsible for inserting fresh entries or updating existing entries in the program cache.
623-
When the client boots up, the program cache is empty. As programs get invoked, this function is responsible
624-
for verifying and inserting these programs into the cache. Additionally, this function performs reverification
625-
checks for every existing program that is invoked after an epoch boundary once per program per epoch, and invalidates
626-
any programs that fail reverification.
627-
628-
When the cluster's feature set changes at an epoch, there is a possibility that existing programs
629-
fail new SBPF / ELF header checks. Therefore, after every epoch, we should reverify all programs
630-
and update our program cache so that users cannot invoke those old programs. Since iterating through
631-
all programs every single epoch is expensive, we adopt a lazy approach where we reverify programs as they
632-
are referenced in transactions, since only a small subset of all programs are actually referenced at any
633-
time. We also make sure each program is only verified once per epoch, so repeated executions of a
634-
program within the same epoch will only trigger verification once at the very first invocation.
635-
636-
Note that ALUTs must be resolved because programs referenced in ALUTs can be invoked via CPI. */
622+
/* `fd_runtime_update_program_cache()` is responsible for updating the
623+
program cache with any programs referenced in the current
624+
transaction. See fd_program_cache.h for more details.
625+
626+
Note that ALUTs must be resolved because programs referenced in ALUTs
627+
can be invoked via CPI.
628+
629+
TODO: We need to remove the ALUT resolution from this function
630+
because it is redundant (ALUTs get resolved again in the exec tile). */
637631
void
638632
fd_runtime_update_program_cache( fd_exec_slot_ctx_t * slot_ctx,
639633
fd_txn_p_t const * txn_p,

src/flamenco/runtime/program/Local.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ $(call add-objs,fd_builtin_programs,fd_flamenco)
88
$(call add-hdrs,fd_bpf_loader_serialization.h)
99
$(call add-objs,fd_bpf_loader_serialization,fd_flamenco)
1010

11-
$(call add-hdrs,fd_bpf_program_util.h)
12-
$(call add-objs,fd_bpf_program_util,fd_flamenco)
11+
$(call add-hdrs,fd_program_cache.h)
12+
$(call add-objs,fd_program_cache,fd_flamenco)
1313

1414
### Precompiles
1515

0 commit comments

Comments
 (0)