From a06ab4725349caa27fdaa21f74a6687a74b5f8fa Mon Sep 17 00:00:00 2001 From: Manik Jain Date: Mon, 10 Feb 2025 21:55:43 +0000 Subject: [PATCH] flamenco, pack, feature: implement reserve_minimal_cus_for_builtin_instructions --- src/disco/pack/fd_pack_cost.h | 26 ++-- .../runtime/program/fd_builtin_programs.c | 147 +++++++++++++++++- .../runtime/program/fd_builtin_programs.h | 93 ++--------- .../program/fd_compute_budget_program.c | 90 +++++++++-- .../program/fd_compute_budget_program.h | 9 ++ src/flamenco/runtime/tests/fd_dump_pb.c | 96 ++++++------ .../runtime/tests/run_ledger_tests_all.txt | 3 +- 7 files changed, 317 insertions(+), 147 deletions(-) diff --git a/src/disco/pack/fd_pack_cost.h b/src/disco/pack/fd_pack_cost.h index d798b6f695..79c356cb7a 100644 --- a/src/disco/pack/fd_pack_cost.h +++ b/src/disco/pack/fd_pack_cost.h @@ -50,20 +50,18 @@ typedef struct fd_pack_builtin_prog_cost fd_pack_builtin_prog_cost_t; #define MAP_PERFECT_HASH_R( ptr ) PERFECT_HASH( fd_uint_load_4( (uchar const *)ptr->b + 8UL ) ) -#define VOTE_PROG_COST 3000UL - -#define MAP_PERFECT_0 ( STAKE_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_1 ( CONFIG_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_2 ( VOTE_PROG_ID ), .cost_per_instr=VOTE_PROG_COST -#define MAP_PERFECT_3 ( SYS_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_4 ( COMPUTE_BUDGET_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_5 ( BPF_UPGRADEABLE_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_6 ( BPF_LOADER_1_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_7 ( BPF_LOADER_2_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_8 ( LOADER_V4_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_9 ( KECCAK_SECP_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_10 ( ED25519_SV_PROG_ID ), .cost_per_instr= 3000UL -#define MAP_PERFECT_11 ( SECP256R1_PROG_ID ), .cost_per_instr= 3000UL +/* The cost model estimates 200,000 CUs for builtin programs that were migrated to BPF */ +#define VOTE_PROG_COST 3000UL + +#define MAP_PERFECT_0 ( VOTE_PROG_ID ), .cost_per_instr= VOTE_PROG_COST +#define MAP_PERFECT_1 ( SYS_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_2 ( COMPUTE_BUDGET_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_3 ( BPF_UPGRADEABLE_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_4 ( BPF_LOADER_1_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_5 ( BPF_LOADER_2_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_6 ( LOADER_V4_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_7 ( KECCAK_SECP_PROG_ID ), .cost_per_instr= 3000UL +#define MAP_PERFECT_8 ( ED25519_SV_PROG_ID ), .cost_per_instr= 3000UL #include "../../util/tmpl/fd_map_perfect.c" diff --git a/src/flamenco/runtime/program/fd_builtin_programs.c b/src/flamenco/runtime/program/fd_builtin_programs.c index 188f291f49..1f7b9349d5 100644 --- a/src/flamenco/runtime/program/fd_builtin_programs.c +++ b/src/flamenco/runtime/program/fd_builtin_programs.c @@ -2,7 +2,124 @@ #include "../fd_acc_mgr.h" #include "../fd_system_ids.h" #include "../fd_system_ids_pp.h" -#include + +#define BUILTIN_PROGRAM(program_id, name, feature_offset, migration_config) \ + { \ + program_id, \ + name, \ + feature_offset, \ + migration_config \ + } + +#define STATELESS_BUILTIN(program_id, migration_config) \ + { \ + program_id, \ + migration_config \ + } + +#define CORE_BPF_MIGRATION_CONFIG(source_buffer_address, upgrade_authority_address, enable_feature_offset, builtin_program_id) \ + { \ + source_buffer_address, \ + upgrade_authority_address, \ + enable_feature_offset, \ + builtin_program_id \ + } + +#define NO_CORE_BPF_MIGRATION_CONFIG NULL + +#define DEFINE_CORE_BPF_MIGRATION_CONFIG(name, buffer_address, feature_offset, program_id) \ + static const fd_core_bpf_migration_config_t name = { \ + buffer_address, \ + NULL, \ + offsetof(fd_features_t, feature_offset), \ + program_id \ + }; \ + static const fd_core_bpf_migration_config_t * const MIGRATE_##name = &name + +DEFINE_CORE_BPF_MIGRATION_CONFIG(BUILTIN_TO_CORE_BPF_STAKE_PROGRAM_CONFIG, &fd_solana_stake_program_buffer_address, migrate_stake_program_to_core_bpf, &fd_solana_stake_program_id); +DEFINE_CORE_BPF_MIGRATION_CONFIG(BUILTIN_TO_CORE_BPF_CONFIG_PROGRAM_CONFIG, &fd_solana_config_program_buffer_address, migrate_config_program_to_core_bpf, &fd_solana_config_program_id); +DEFINE_CORE_BPF_MIGRATION_CONFIG(BUILTIN_TO_CORE_BPF_ADDRESS_LOOKUP_TABLE_PROGRAM_CONFIG, &fd_solana_address_lookup_table_program_buffer_address, migrate_address_lookup_table_program_to_core_bpf, &fd_solana_address_lookup_table_program_id); +DEFINE_CORE_BPF_MIGRATION_CONFIG(STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG, &fd_solana_feature_program_buffer_address, migrate_feature_gate_program_to_core_bpf, &fd_solana_feature_program_id); + +#define SYSTEM_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_system_program_id, "system_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) +#define VOTE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_vote_program_id, "vote_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) +#define STAKE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_stake_program_id, "stake_program", NO_ENABLE_FEATURE_ID, MIGRATE_BUILTIN_TO_CORE_BPF_STAKE_PROGRAM_CONFIG) +#define CONFIG_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_config_program_id, "config_program", NO_ENABLE_FEATURE_ID, MIGRATE_BUILTIN_TO_CORE_BPF_CONFIG_PROGRAM_CONFIG) +#define LOADER_V4_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_v4_program_id, "loader_v4", offsetof(fd_features_t, enable_program_runtime_v2_and_loader_v4), NO_CORE_BPF_MIGRATION_CONFIG) +#define ADDRESS_LOOKUP_TABLE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_address_lookup_table_program_id, "address_lookup_table_program", NO_ENABLE_FEATURE_ID, MIGRATE_BUILTIN_TO_CORE_BPF_ADDRESS_LOOKUP_TABLE_PROGRAM_CONFIG) +#define BPF_LOADER_DEPRECATED_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_deprecated_program_id, "solana_bpf_loader_deprecated_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) +#define BPF_LOADER_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_program_id, "solana_bpf_loader_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) +#define BPF_LOADER_UPGRADEABLE_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_upgradeable_program_id, "solana_bpf_loader_upgradeable_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) +#define COMPUTE_BUDGET_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_compute_budget_program_id, "compute_budget_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) +#define ZK_TOKEN_PROOF_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_zk_token_proof_program_id, "zk_token_proof_program", offsetof(fd_features_t, zk_token_sdk_enabled), NO_CORE_BPF_MIGRATION_CONFIG) +#define ZK_ELGAMAL_PROOF_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_zk_elgamal_proof_program_id, "zk_elgamal_proof_program", offsetof(fd_features_t, zk_elgamal_proof_program_enabled), NO_CORE_BPF_MIGRATION_CONFIG) + +#define FEATURE_PROGRAM_BUILTIN STATELESS_BUILTIN(&fd_solana_feature_program_id, MIGRATE_STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG) + +/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/mod.rs#L133-L143 */ +static const fd_stateless_builtin_program_t stateless_programs_builtins[] = { + FEATURE_PROGRAM_BUILTIN +}; +#define STATELESS_BUILTINS_COUNT (sizeof(stateless_programs_builtins) / sizeof(fd_stateless_builtin_program_t)) + +/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/mod.rs#L34-L131 */ +fd_builtin_program_t const builtin_programs[] = { + SYSTEM_PROGRAM_BUILTIN, + VOTE_PROGRAM_BUILTIN, + STAKE_PROGRAM_BUILTIN, + CONFIG_PROGRAM_BUILTIN, + LOADER_V4_BUILTIN, + ADDRESS_LOOKUP_TABLE_PROGRAM_BUILTIN, + BPF_LOADER_DEPRECATED_BUILTIN, + BPF_LOADER_BUILTIN, + BPF_LOADER_UPGRADEABLE_BUILTIN, + COMPUTE_BUDGET_PROGRAM_BUILTIN, + ZK_TOKEN_PROOF_PROGRAM_BUILTIN, + ZK_ELGAMAL_PROOF_PROGRAM_BUILTIN +}; +#define BUILTIN_PROGRAMS_COUNT (sizeof(builtin_programs) / sizeof(fd_builtin_program_t)) + +/* Used by the compute budget program to determine how many CUs to deduct by default + https://github.com/anza-xyz/agave/blob/v2.1.13/builtins-default-costs/src/lib.rs#L113-L139 */ +fd_core_bpf_migration_config_t const * migrating_builtins[] = { + MIGRATE_BUILTIN_TO_CORE_BPF_STAKE_PROGRAM_CONFIG, + MIGRATE_BUILTIN_TO_CORE_BPF_CONFIG_PROGRAM_CONFIG, + MIGRATE_BUILTIN_TO_CORE_BPF_ADDRESS_LOOKUP_TABLE_PROGRAM_CONFIG, +}; +#define MIGRATING_BUILTINS_COUNT (sizeof(migrating_builtins) / sizeof(fd_core_bpf_migration_config_t const *)) + +/* Using MAP_PERFECT instead of a list for optimization + https://github.com/anza-xyz/agave/blob/v2.1.13/builtins-default-costs/src/lib.rs#L141-L193 */ +#define MAP_PERFECT_NAME fd_non_migrating_builtins_tbl +#define MAP_PERFECT_LG_TBL_SZ 4 +#define MAP_PERFECT_T fd_pubkey_t +#define MAP_PERFECT_HASH_C 146U +#define MAP_PERFECT_KEY uc +#define MAP_PERFECT_KEY_T fd_pubkey_t const * +#define MAP_PERFECT_ZERO_KEY (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define MAP_PERFECT_COMPLEX_KEY 1 +#define MAP_PERFECT_KEYS_EQUAL(k1,k2) (!memcmp( (k1), (k2), 32UL )) + +#define PERFECT_HASH( u ) (((MAP_PERFECT_HASH_C*(u))>>28)&0x0FU) + +#define MAP_PERFECT_HASH_PP( a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15, \ + a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) \ + PERFECT_HASH( (a08 | (a09<<8) | (a10<<16) | (a11<<24)) ) +#define MAP_PERFECT_HASH_R( ptr ) PERFECT_HASH( fd_uint_load_4( (uchar const *)ptr->uc + 8UL ) ) + +#define MAP_PERFECT_0 ( VOTE_PROG_ID ), +#define MAP_PERFECT_1 ( SYS_PROG_ID ), +#define MAP_PERFECT_2 ( COMPUTE_BUDGET_PROG_ID ), +#define MAP_PERFECT_3 ( BPF_UPGRADEABLE_PROG_ID ), +#define MAP_PERFECT_4 ( BPF_LOADER_1_PROG_ID ), +#define MAP_PERFECT_5 ( BPF_LOADER_2_PROG_ID ), +#define MAP_PERFECT_6 ( LOADER_V4_PROG_ID ), +#define MAP_PERFECT_7 ( KECCAK_SECP_PROG_ID ), +#define MAP_PERFECT_8 ( ED25519_SV_PROG_ID ), + +#include "../../../util/tmpl/fd_map_perfect.c" +#undef PERFECT_HASH + /* BuiltIn programs need "bogus" executable accounts to exist. These are loaded and ignored during execution. @@ -129,3 +246,31 @@ ulong fd_num_stateless_builtins( void ) { return STATELESS_BUILTINS_COUNT; } + +uchar +fd_is_migrating_builtin_program( fd_exec_slot_ctx_t const * slot_ctx, + fd_pubkey_t const * pubkey, + uchar * migrated_yet ) { + *migrated_yet = 0; + + for( ulong i=0; iuc, config->builtin_program_id->key, sizeof(fd_pubkey_t) ) ) { + if( config->enable_feature_offset!=NO_ENABLE_FEATURE_ID && + FD_FEATURE_ACTIVE_OFFSET( slot_ctx, config->enable_feature_offset ) ) { + /* The program has been migrated to BPF. */ + *migrated_yet = 1; + } + + return 1; + } + } + + /* No migration config exists for this program */ + return 0; +} + +FD_FN_PURE uchar +fd_is_non_migrating_builtin_program( fd_pubkey_t const * pubkey ) { + return !!( fd_non_migrating_builtins_tbl_contains( pubkey ) ); +} diff --git a/src/flamenco/runtime/program/fd_builtin_programs.h b/src/flamenco/runtime/program/fd_builtin_programs.h index c14b6e3fc7..af50c3523a 100644 --- a/src/flamenco/runtime/program/fd_builtin_programs.h +++ b/src/flamenco/runtime/program/fd_builtin_programs.h @@ -63,83 +63,22 @@ fd_stateless_builtins( void ); ulong fd_num_stateless_builtins( void ); -FD_PROTOTYPES_END - -#define BUILTIN_PROGRAM(program_id, name, feature_offset, migration_config) \ - { \ - program_id, \ - name, \ - feature_offset, \ - migration_config \ - } - -#define STATELESS_BUILTIN(program_id, migration_config) \ - { \ - program_id, \ - migration_config \ - } - -#define CORE_BPF_MIGRATION_CONFIG(source_buffer_address, upgrade_authority_address, enable_feature_offset, builtin_program_id) \ - { \ - source_buffer_address, \ - upgrade_authority_address, \ - enable_feature_offset, \ - builtin_program_id \ - } - -#define NO_CORE_BPF_MIGRATION_CONFIG NULL - -#define DEFINE_CORE_BPF_MIGRATION_CONFIG(name, buffer_address, feature_offset, program_id) \ - static const fd_core_bpf_migration_config_t name = { \ - buffer_address, \ - NULL, \ - offsetof(fd_features_t, feature_offset), \ - program_id \ - }; \ - static const fd_core_bpf_migration_config_t * const MIGRATE_##name = &name - -DEFINE_CORE_BPF_MIGRATION_CONFIG(BUILTIN_TO_CORE_BPF_STAKE_PROGRAM_CONFIG, &fd_solana_stake_program_buffer_address, migrate_stake_program_to_core_bpf, &fd_solana_stake_program_id); -DEFINE_CORE_BPF_MIGRATION_CONFIG(BUILTIN_TO_CORE_BPF_CONFIG_PROGRAM_CONFIG, &fd_solana_config_program_buffer_address, migrate_config_program_to_core_bpf, &fd_solana_config_program_id); -DEFINE_CORE_BPF_MIGRATION_CONFIG(BUILTIN_TO_CORE_BPF_ADDRESS_LOOKUP_TABLE_PROGRAM_CONFIG, &fd_solana_address_lookup_table_program_buffer_address, migrate_address_lookup_table_program_to_core_bpf, &fd_solana_address_lookup_table_program_id); -DEFINE_CORE_BPF_MIGRATION_CONFIG(STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG, &fd_solana_feature_program_buffer_address, migrate_feature_gate_program_to_core_bpf, &fd_solana_feature_program_id); - -#define SYSTEM_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_system_program_id, "system_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) -#define VOTE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_vote_program_id, "vote_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) -#define STAKE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_stake_program_id, "stake_program", NO_ENABLE_FEATURE_ID, MIGRATE_BUILTIN_TO_CORE_BPF_STAKE_PROGRAM_CONFIG) -#define CONFIG_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_config_program_id, "config_program", NO_ENABLE_FEATURE_ID, MIGRATE_BUILTIN_TO_CORE_BPF_CONFIG_PROGRAM_CONFIG) -#define LOADER_V4_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_v4_program_id, "loader_v4", offsetof(fd_features_t, enable_program_runtime_v2_and_loader_v4), NO_CORE_BPF_MIGRATION_CONFIG) -#define ADDRESS_LOOKUP_TABLE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_address_lookup_table_program_id, "address_lookup_table_program", NO_ENABLE_FEATURE_ID, MIGRATE_BUILTIN_TO_CORE_BPF_ADDRESS_LOOKUP_TABLE_PROGRAM_CONFIG) -#define BPF_LOADER_DEPRECATED_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_deprecated_program_id, "solana_bpf_loader_deprecated_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) -#define BPF_LOADER_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_program_id, "solana_bpf_loader_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) -#define BPF_LOADER_UPGRADEABLE_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_upgradeable_program_id, "solana_bpf_loader_upgradeable_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) -#define COMPUTE_BUDGET_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_compute_budget_program_id, "compute_budget_program", NO_ENABLE_FEATURE_ID, NO_CORE_BPF_MIGRATION_CONFIG) -#define ZK_TOKEN_PROOF_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_zk_token_proof_program_id, "zk_token_proof_program", offsetof(fd_features_t, zk_token_sdk_enabled), NO_CORE_BPF_MIGRATION_CONFIG) -#define ZK_ELGAMAL_PROOF_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_zk_elgamal_proof_program_id, "zk_elgamal_proof_program", offsetof(fd_features_t, zk_elgamal_proof_program_enabled), NO_CORE_BPF_MIGRATION_CONFIG) - -#define FEATURE_PROGRAM_BUILTIN STATELESS_BUILTIN(&fd_solana_feature_program_id, MIGRATE_STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG) - -/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/mod.rs#L34-L131 */ -static const fd_builtin_program_t builtin_programs[] = { - SYSTEM_PROGRAM_BUILTIN, - VOTE_PROGRAM_BUILTIN, - STAKE_PROGRAM_BUILTIN, - CONFIG_PROGRAM_BUILTIN, - LOADER_V4_BUILTIN, - ADDRESS_LOOKUP_TABLE_PROGRAM_BUILTIN, - BPF_LOADER_DEPRECATED_BUILTIN, - BPF_LOADER_BUILTIN, - BPF_LOADER_UPGRADEABLE_BUILTIN, - COMPUTE_BUDGET_PROGRAM_BUILTIN, - ZK_TOKEN_PROOF_PROGRAM_BUILTIN, - ZK_ELGAMAL_PROOF_PROGRAM_BUILTIN -}; -#define BUILTIN_PROGRAMS_COUNT sizeof(builtin_programs) / sizeof(fd_builtin_program_t) +/* `migrated_yet` is an output value thats set based on the rules below: + + | Return Value | *migrated_yet | Description | + |--------------|-------------------|--------------------------------------------------------------------------| + | 0 | 0 | Program is not a migrating builtin program | + | 1 | 0 | Program is a migrating builtin program id, BUT has not been migrated yet | + | 1 | 1 | Program is a migrating builtin program id, AND has been migrated to BPF | +*/ +uchar +fd_is_migrating_builtin_program( fd_exec_slot_ctx_t const * slot_ctx, + fd_pubkey_t const * pubkey, + uchar * migrated_yet ); + +uchar +fd_is_non_migrating_builtin_program( fd_pubkey_t const * pubkey ); - -/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/mod.rs#L133-L143 */ -static const fd_stateless_builtin_program_t stateless_programs_builtins[] = { - FEATURE_PROGRAM_BUILTIN -}; -#define STATELESS_BUILTINS_COUNT sizeof(stateless_programs_builtins) / sizeof(fd_stateless_builtin_program_t) +FD_PROTOTYPES_END #endif /* HEADER_fd_src_flamenco_runtime_program_fd_buildin_programs_h */ diff --git a/src/flamenco/runtime/program/fd_compute_budget_program.c b/src/flamenco/runtime/program/fd_compute_budget_program.c index d9e9c73144..4f25a86f32 100644 --- a/src/flamenco/runtime/program/fd_compute_budget_program.c +++ b/src/flamenco/runtime/program/fd_compute_budget_program.c @@ -8,9 +8,41 @@ #include "../context/fd_exec_slot_ctx.h" #include "../context/fd_exec_epoch_ctx.h" #include "../../vm/fd_vm.h" +#include "fd_builtin_programs.h" -#define DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT (200000) -#define DEFAULT_COMPUTE_UNITS (150UL) +#define DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT (200000UL) +#define DEFAULT_COMPUTE_UNITS (150UL) + +/* https://github.com/anza-xyz/agave/blob/v2.1.13/compute-budget/src/compute_budget_limits.rs#L11-L13 */ +#define MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT (3000UL) + +FD_FN_PURE static inline uchar +get_program_kind( fd_exec_txn_ctx_t const * ctx, + fd_txn_instr_t const * instr ) { + fd_pubkey_t const * txn_accs = ctx->accounts; + fd_pubkey_t const * program_pubkey = &txn_accs[ instr->program_id ]; + + /* The program is a standard, non-migrating builtin (e.g. system program) */ + if( fd_is_non_migrating_builtin_program( program_pubkey ) ) { + return FD_PROGRAM_KIND_BUILTIN; + } + + uchar migrated_yet; + uchar is_migrating_program = fd_is_migrating_builtin_program( ctx->slot_ctx, program_pubkey, &migrated_yet ); + + /* The program has a BPF migration config but has not been migrated yet, so it's still a builtin program */ + if( is_migrating_program && !migrated_yet ) { + return FD_PROGRAM_KIND_BUILTIN; + } + + /* The program has a BPF migration config AND has been migrated */ + if( is_migrating_program && migrated_yet ) { + return FD_PROGRAM_KIND_MIGRATING_BUILTIN; + } + + /* The program is some other program kind, i.e. not a builtin */ + return FD_PROGRAM_KIND_NOT_BUILTIN; +} FD_FN_PURE static inline int is_compute_budget_instruction( fd_exec_txn_ctx_t const * ctx, @@ -20,6 +52,26 @@ is_compute_budget_instruction( fd_exec_txn_ctx_t const * ctx, return !memcmp(program_pubkey, fd_solana_compute_budget_program_id.key, sizeof(fd_pubkey_t)); } +/* In our implementation of this function, our parameters map to Agave's as follows: + - `num_builtin_instrs` -> `num_non_migratable_builtin_instructions` + `num_not_migrated` + - `num_non_builtin_instrs` -> `num_non_builtin_instructions` + `num_migrated` + + https://github.com/anza-xyz/agave/blob/v2.1.13/runtime-transaction/src/compute_budget_instruction_details.rs#L211-L239 */ +FD_FN_PURE static inline ulong +calculate_default_compute_unit_limit( fd_exec_txn_ctx_t const * ctx, + ulong num_builtin_instrs, + ulong num_non_builtin_instrs, + ulong num_non_compute_budget_instrs ) { + if( FD_FEATURE_ACTIVE( ctx->slot_ctx, reserve_minimal_cus_for_builtin_instructions ) ) { + /* https://github.com/anza-xyz/agave/blob/v2.1.13/runtime-transaction/src/compute_budget_instruction_details.rs#L227-L234 */ + return fd_ulong_sat_add( fd_ulong_sat_mul( num_builtin_instrs, MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT ), + fd_ulong_sat_mul( num_non_builtin_instrs, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT ) ); + } else { + /* https://github.com/anza-xyz/agave/blob/v2.1.13/runtime-transaction/src/compute_budget_instruction_details.rs#L236-L237 */ + return fd_ulong_sat_mul( num_non_compute_budget_instrs, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT ); + } +} + /* https://github.com/anza-xyz/agave/blob/16de8b75ebcd57022409b422de557dd37b1de8db/compute-budget/src/compute_budget_processor.rs#L150-L153 */ FD_FN_PURE static inline int sanitize_requested_heap_size( ulong bytes ) { @@ -27,7 +79,7 @@ sanitize_requested_heap_size( ulong bytes ) { } /* https://github.com/anza-xyz/agave/blob/16de8b75ebcd57022409b422de557dd37b1de8db/compute-budget/src/compute_budget_processor.rs#L69-L148 */ -int +int fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx, fd_rawtxn_b_t const * txn_raw ) { uint has_compute_units_limit_update = 0UL; uint has_compute_units_price_update = 0UL; @@ -35,7 +87,12 @@ fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx uint has_loaded_accounts_data_size_limit_update = 0UL; ushort requested_heap_size_instr_index = 0; - uint num_non_compute_budget_instrs = 0U; + + /* SIMD-170 introduces a conservative CU limit of 3,000 CUs per non-migrated native program, + and 200,000 CUs for all other programs (including migrated builtins). */ + ulong num_non_compute_budget_instrs = 0UL; + ulong num_builtin_instrs = 0UL; + ulong num_non_builtin_instrs = 0UL; uint updated_compute_unit_limit = 0U; uint updated_requested_heap_size = 0U; @@ -47,10 +104,22 @@ fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx for( ushort i=0; itxn_descriptor->instr_cnt; i++ ) { fd_txn_instr_t const * instr = &ctx->txn_descriptor->instr[i]; + /* Track builtin vs non-builtin metrics only if SIMD-170 is active */ + if( FD_FEATURE_ACTIVE( ctx->slot_ctx, reserve_minimal_cus_for_builtin_instructions ) ) { + /* Only `FD_PROGRAM_KIND_BUILTIN` gets charged as a builtin instruction */ + uchar program_kind = get_program_kind( ctx, instr ); + if( program_kind==FD_PROGRAM_KIND_BUILTIN ) { + num_builtin_instrs++; + } else { + num_non_builtin_instrs++; + } + } + if( !is_compute_budget_instruction( ctx, instr ) ) { num_non_compute_budget_instrs++; continue; } + /* Deserialize the ComputeBudgetInstruction enum */ uchar * data = (uchar *)txn_raw->raw + instr->data_off; @@ -122,16 +191,19 @@ fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx if( FD_UNLIKELY( !sanitize_requested_heap_size( updated_requested_heap_size ) ) ) { FD_TXN_ERR_FOR_LOG_INSTR( ctx, FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA, requested_heap_size_instr_index ); return FD_RUNTIME_TXN_ERR_INSTRUCTION_ERROR; - } + } ctx->heap_size = updated_requested_heap_size; } - /* https://github.com/anza-xyz/agave/blob/v2.1/runtime-transaction/src/compute_budget_instruction_details.rs#L66-L76 */ + /* https://github.com/anza-xyz/agave/blob/v2.1.13/runtime-transaction/src/compute_budget_instruction_details.rs#L137-L143 */ if( has_compute_units_limit_update ) { ctx->compute_unit_limit = fd_ulong_min( FD_MAX_COMPUTE_UNIT_LIMIT, updated_compute_unit_limit ); } else { - ctx->compute_unit_limit = fd_ulong_min( FD_MAX_COMPUTE_UNIT_LIMIT, - (ulong)fd_uint_sat_mul( num_non_compute_budget_instrs, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT ) ); + ctx->compute_unit_limit = fd_ulong_min( calculate_default_compute_unit_limit(ctx, + num_builtin_instrs, + num_non_builtin_instrs, + num_non_compute_budget_instrs), + FD_MAX_COMPUTE_UNIT_LIMIT ); } ctx->compute_meter = ctx->compute_unit_limit; @@ -145,7 +217,7 @@ fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx if( FD_UNLIKELY( updated_loaded_accounts_data_size_limit==0UL ) ) { return FD_RUNTIME_TXN_ERR_INVALID_LOADED_ACCOUNTS_DATA_SIZE_LIMIT; } - ctx->loaded_accounts_data_size_limit = + ctx->loaded_accounts_data_size_limit = fd_ulong_min( FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT, updated_loaded_accounts_data_size_limit ); } diff --git a/src/flamenco/runtime/program/fd_compute_budget_program.h b/src/flamenco/runtime/program/fd_compute_budget_program.h index 0c0f2853e9..e39ff6bd05 100644 --- a/src/flamenco/runtime/program/fd_compute_budget_program.h +++ b/src/flamenco/runtime/program/fd_compute_budget_program.h @@ -13,6 +13,15 @@ #define FD_COMPUTE_BUDGET_PRIORITIZATION_FEE_TYPE_COMPUTE_UNIT_PRICE (0) #define FD_COMPUTE_BUDGET_PRIORITIZATION_FEE_TYPE_DEPRECATED (1) +/* SIMD-170 defines new default compute units for builtin, non-builtin, and migrated programs: + - Any non-migrated builtins have a conservative default CU limit of 3,000 CUs. + - Any migrated and non-builtins have a default CU limit of 200,000 CUs. + + https://github.com/anza-xyz/agave/blob/v2.1.13/runtime-transaction/src/builtin_programs_filter.rs#L9-L19 */ +#define FD_PROGRAM_KIND_NOT_BUILTIN (0) +#define FD_PROGRAM_KIND_BUILTIN (1) +#define FD_PROGRAM_KIND_MIGRATING_BUILTIN (2) + FD_PROTOTYPES_BEGIN int fd_executor_compute_budget_program_execute_instructions( fd_exec_txn_ctx_t * ctx, fd_rawtxn_b_t const * txn_raw ); diff --git a/src/flamenco/runtime/tests/fd_dump_pb.c b/src/flamenco/runtime/tests/fd_dump_pb.c index e7a6f6201b..51ce81958f 100644 --- a/src/flamenco/runtime/tests/fd_dump_pb.c +++ b/src/flamenco/runtime/tests/fd_dump_pb.c @@ -8,9 +8,11 @@ /***** UTILITY FUNCTIONS *****/ static void -dump_sorted_features( const fd_features_t * features, fd_exec_test_feature_set_t * output_feature_set ) { +dump_sorted_features( fd_features_t const * features, + fd_exec_test_feature_set_t * output_feature_set, + fd_spad_t * spad ) { /* NOTE: Caller must have a scratch frame prepared */ - uint64_t * unsorted_features = fd_scratch_alloc( alignof(uint64_t), FD_FEATURE_ID_CNT * sizeof(uint64_t) ); + uint64_t * unsorted_features = fd_spad_alloc( spad, alignof(uint64_t), FD_FEATURE_ID_CNT * sizeof(uint64_t) ); ulong num_features = 0; for( const fd_feature_id_t * current_feature = fd_feature_iter_init(); !fd_feature_iter_done( current_feature ); current_feature = fd_feature_iter_next( current_feature ) ) { if (features->f[current_feature->index] != FD_FEATURE_DISABLED) { @@ -18,7 +20,7 @@ dump_sorted_features( const fd_features_t * features, fd_exec_test_feature_set_t } } // Sort the features - void * scratch = fd_scratch_alloc( sort_uint64_t_stable_scratch_align(), sort_uint64_t_stable_scratch_footprint(num_features) ); + void * scratch = fd_spad_alloc( spad, sort_uint64_t_stable_scratch_align(), sort_uint64_t_stable_scratch_footprint(num_features) ); uint64_t * sorted_features = sort_uint64_t_stable_fast( unsorted_features, num_features, scratch ); // Set feature set in message @@ -28,7 +30,8 @@ dump_sorted_features( const fd_features_t * features, fd_exec_test_feature_set_t static void dump_account_state( fd_borrowed_account_t const * borrowed_account, - fd_exec_test_acct_state_t * output_account ) { + fd_exec_test_acct_state_t * output_account, + fd_spad_t * spad ) { // Address fd_memcpy(output_account->address, borrowed_account->pubkey, sizeof(fd_pubkey_t)); @@ -36,7 +39,7 @@ dump_account_state( fd_borrowed_account_t const * borrowed_account, output_account->lamports = (uint64_t) borrowed_account->const_meta->info.lamports; // Data - output_account->data = fd_scratch_alloc(alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(borrowed_account->const_meta->dlen)); + output_account->data = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( borrowed_account->const_meta->dlen ) ); output_account->data->size = (pb_size_t) borrowed_account->const_meta->dlen; fd_memcpy(output_account->data->bytes, borrowed_account->const_data, borrowed_account->const_meta->dlen); @@ -106,8 +109,9 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m */ // Dump regular accounts first txn_context_msg->account_shared_data_count = 0; - txn_context_msg->account_shared_data = fd_scratch_alloc( alignof(fd_exec_test_acct_state_t), - (txn_ctx->accounts_cnt * 2 + txn_descriptor->addr_table_lookup_cnt + num_sysvar_entries) * sizeof(fd_exec_test_acct_state_t) ); + txn_context_msg->account_shared_data = fd_spad_alloc( spad, + alignof(fd_exec_test_acct_state_t), + (txn_ctx->accounts_cnt * 2 + txn_descriptor->addr_table_lookup_cnt + num_sysvar_entries) * sizeof(fd_exec_test_acct_state_t) ); for( ulong i = 0; i < txn_ctx->accounts_cnt; ++i ) { FD_BORROWED_ACCOUNT_DECL(borrowed_account); int ret = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, &txn_ctx->accounts[i], borrowed_account ); @@ -124,7 +128,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m } } if( !is_builtin ) { - dump_account_state( borrowed_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++] ); + dump_account_state( borrowed_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++], spad ); } } @@ -140,7 +144,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m if( !txn_ctx->executable_accounts[i].const_meta ) { continue; } - dump_account_state( &txn_ctx->executable_accounts[i], &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++] ); + dump_account_state( &txn_ctx->executable_accounts[i], &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++], spad ); } // Reset state @@ -157,7 +161,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m if( FD_UNLIKELY(ret != FD_ACC_MGR_SUCCESS) ) { continue; } - dump_account_state( borrowed_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++] ); + dump_account_state( borrowed_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++], spad ); } // Dump sysvars @@ -178,7 +182,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m } // Copy it into output if (!account_exists) { - dump_account_state( borrowed_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++] ); + dump_account_state( borrowed_account, &txn_context_msg->account_shared_data[txn_context_msg->account_shared_data_count++], spad ); } } @@ -208,10 +212,10 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m /* Transaction Context -> tx -> message -> account_keys */ message->account_keys_count = txn_descriptor->acct_addr_cnt; - message->account_keys = fd_scratch_alloc( alignof(pb_bytes_array_t *), PB_BYTES_ARRAY_T_ALLOCSIZE(txn_descriptor->acct_addr_cnt * sizeof(pb_bytes_array_t *)) ); + message->account_keys = fd_spad_alloc( spad, alignof(pb_bytes_array_t *), PB_BYTES_ARRAY_T_ALLOCSIZE( txn_descriptor->acct_addr_cnt * sizeof(pb_bytes_array_t *) ) ); fd_acct_addr_t const * account_keys = fd_txn_get_acct_addrs( txn_descriptor, txn_payload ); for( ulong i = 0; i < txn_descriptor->acct_addr_cnt; i++ ) { - pb_bytes_array_t * account_key = fd_scratch_alloc( alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(sizeof(fd_pubkey_t)) ); + pb_bytes_array_t * account_key = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( sizeof(fd_pubkey_t) ) ); account_key->size = sizeof(fd_pubkey_t); memcpy( account_key->bytes, &account_keys[i], sizeof(fd_pubkey_t) ); message->account_keys[i] = account_key; @@ -219,13 +223,13 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m /* Transaction Context -> tx -> message -> recent_blockhash */ uchar const * recent_blockhash = fd_txn_get_recent_blockhash( txn_descriptor, txn_payload ); - message->recent_blockhash = fd_scratch_alloc( alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(sizeof(fd_hash_t)) ); + message->recent_blockhash = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( sizeof(fd_hash_t) ) ); message->recent_blockhash->size = sizeof(fd_hash_t); memcpy( message->recent_blockhash->bytes, recent_blockhash, sizeof(fd_hash_t) ); /* Transaction Context -> tx -> message -> instructions */ message->instructions_count = txn_descriptor->instr_cnt; - message->instructions = fd_scratch_alloc( alignof(fd_exec_test_compiled_instruction_t), txn_descriptor->instr_cnt * sizeof(fd_exec_test_compiled_instruction_t) ); + message->instructions = fd_spad_alloc( spad, alignof(fd_exec_test_compiled_instruction_t), txn_descriptor->instr_cnt * sizeof(fd_exec_test_compiled_instruction_t) ); for( ulong i = 0; i < txn_descriptor->instr_cnt; ++i ) { fd_txn_instr_t instr = txn_descriptor->instr[i]; fd_exec_test_compiled_instruction_t * compiled_instruction = &message->instructions[i]; @@ -235,7 +239,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m // compiled instruction -> accounts compiled_instruction->accounts_count = instr.acct_cnt; - compiled_instruction->accounts = fd_scratch_alloc( alignof(uint32_t), instr.acct_cnt * sizeof(uint32_t) ); + compiled_instruction->accounts = fd_spad_alloc( spad, alignof(uint32_t), instr.acct_cnt * sizeof(uint32_t) ); uchar const * instr_accounts = fd_txn_get_instr_accts( &instr, txn_payload ); for( ulong j = 0; j < instr.acct_cnt; ++j ) { uchar instr_acct_index = instr_accounts[j]; @@ -244,7 +248,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m // compiled instruction -> data uchar const * instr_data = fd_txn_get_instr_data( &instr, txn_payload ); - compiled_instruction->data = fd_scratch_alloc( alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(instr.data_sz) ); + compiled_instruction->data = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( instr.data_sz ) ); compiled_instruction->data->size = instr.data_sz; memcpy( compiled_instruction->data->bytes, instr_data, instr.data_sz ); } @@ -254,8 +258,9 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m if( !message->is_legacy ) { /* Transaction Context -> tx -> message -> address_table_lookups */ message->address_table_lookups_count = txn_descriptor->addr_table_lookup_cnt; - message->address_table_lookups = fd_scratch_alloc( alignof(fd_exec_test_message_address_table_lookup_t), - txn_descriptor->addr_table_lookup_cnt * sizeof(fd_exec_test_message_address_table_lookup_t) ); + message->address_table_lookups = fd_spad_alloc( spad, + alignof(fd_exec_test_message_address_table_lookup_t), + txn_descriptor->addr_table_lookup_cnt * sizeof(fd_exec_test_message_address_table_lookup_t) ); for( ulong i = 0; i < txn_descriptor->addr_table_lookup_cnt; ++i ) { // alut -> account_key fd_pubkey_t * alut_key = (fd_pubkey_t *) (txn_payload + address_lookup_tables[i].addr_off); @@ -270,7 +275,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m // alut -> writable_indexes message->address_table_lookups[i].writable_indexes_count = address_lookup_tables[i].writable_cnt; - message->address_table_lookups[i].writable_indexes = fd_scratch_alloc( alignof(uint32_t), address_lookup_tables[i].writable_cnt * sizeof(uint32_t) ); + message->address_table_lookups[i].writable_indexes = fd_spad_alloc( spad, alignof(uint32_t), address_lookup_tables[i].writable_cnt * sizeof(uint32_t) ); uchar * writable_indexes = (uchar *) (txn_payload + address_lookup_tables[i].writable_off); for( ulong j = 0; j < address_lookup_tables[i].writable_cnt; ++j ) { message->address_table_lookups[i].writable_indexes[j] = writable_indexes[j]; @@ -278,7 +283,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m // alut -> readonly_indexes message->address_table_lookups[i].readonly_indexes_count = address_lookup_tables[i].readonly_cnt; - message->address_table_lookups[i].readonly_indexes = fd_scratch_alloc( alignof(uint32_t), address_lookup_tables[i].readonly_cnt * sizeof(uint32_t) ); + message->address_table_lookups[i].readonly_indexes = fd_spad_alloc( spad, alignof(uint32_t), address_lookup_tables[i].readonly_cnt * sizeof(uint32_t) ); uchar * readonly_indexes = (uchar *) (txn_payload + address_lookup_tables[i].readonly_off); for( ulong j = 0; j < address_lookup_tables[i].readonly_cnt; ++j ) { message->address_table_lookups[i].readonly_indexes[j] = readonly_indexes[j]; @@ -291,10 +296,10 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m /* Transaction Context -> tx -> signatures */ sanitized_transaction->signatures_count = txn_descriptor->signature_cnt; - sanitized_transaction->signatures = fd_scratch_alloc( alignof(pb_bytes_array_t *), PB_BYTES_ARRAY_T_ALLOCSIZE(txn_descriptor->signature_cnt * sizeof(pb_bytes_array_t *)) ); + sanitized_transaction->signatures = fd_spad_alloc( spad, alignof(pb_bytes_array_t *), PB_BYTES_ARRAY_T_ALLOCSIZE( txn_descriptor->signature_cnt * sizeof(pb_bytes_array_t *) ) ); fd_ed25519_sig_t const * signatures = fd_txn_get_signatures( txn_descriptor, txn_payload ); for( uchar i = 0; i < txn_descriptor->signature_cnt; ++i ) { - pb_bytes_array_t * signature = fd_scratch_alloc( alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(sizeof(fd_ed25519_sig_t)) ); + pb_bytes_array_t * signature = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( sizeof(fd_ed25519_sig_t) ) ); signature->size = sizeof(fd_ed25519_sig_t); memcpy( signature->bytes, &signatures[i], sizeof(fd_ed25519_sig_t) ); sanitized_transaction->signatures[i] = signature; @@ -304,9 +309,10 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m NOTE: Agave's implementation of register_hash incorrectly allows the blockhash queue to hold max_age + 1 (max 301) entries. We have this incorrect logic implemented in fd_sysvar_recent_hashes:register_blockhash and it's not a huge issue, but something to keep in mind. */ - pb_bytes_array_t ** output_blockhash_queue = fd_scratch_alloc( + pb_bytes_array_t ** output_blockhash_queue = fd_spad_alloc( + spad, alignof(pb_bytes_array_t *), - PB_BYTES_ARRAY_T_ALLOCSIZE((FD_BLOCKHASH_QUEUE_MAX_ENTRIES + 1) * sizeof(pb_bytes_array_t *)) ); + PB_BYTES_ARRAY_T_ALLOCSIZE( (FD_BLOCKHASH_QUEUE_MAX_ENTRIES + 1) * sizeof(pb_bytes_array_t *) ) ); txn_context_msg->blockhash_queue_count = 0; txn_context_msg->blockhash_queue = output_blockhash_queue; @@ -324,7 +330,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m fd_hash_t blockhash = n->elem.key; // Write the blockhash to the correct index (note we write in reverse order since in the Protobuf message, the oldest blockhash goes first) - pb_bytes_array_t * output_blockhash = fd_scratch_alloc( alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(sizeof(fd_hash_t)) ); + pb_bytes_array_t * output_blockhash = fd_spad_alloc( spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( sizeof(fd_hash_t) ) ); output_blockhash->size = sizeof(fd_hash_t); memcpy( output_blockhash->bytes, &blockhash, sizeof(fd_hash_t) ); output_blockhash_queue[FD_BLOCKHASH_QUEUE_MAX_ENTRIES - queue_index] = output_blockhash; @@ -342,7 +348,7 @@ create_txn_context_protobuf_from_txn( fd_exec_test_txn_context_t * txn_context_m /* Transaction Context -> epoch_ctx */ txn_context_msg->has_epoch_ctx = true; txn_context_msg->epoch_ctx.has_features = true; - dump_sorted_features( &txn_ctx->epoch_ctx->features, &txn_context_msg->epoch_ctx.features ); + dump_sorted_features( &txn_ctx->epoch_ctx->features, &txn_context_msg->epoch_ctx.features, spad ); /* Transaction Context -> slot_ctx */ txn_context_msg->has_slot_ctx = true; @@ -373,12 +379,12 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * /* Accounts */ instr_context->accounts_count = (pb_size_t) txn_ctx->accounts_cnt; - instr_context->accounts = fd_scratch_alloc(alignof(fd_exec_test_acct_state_t), (instr_context->accounts_count + num_sysvar_entries + txn_ctx->executable_cnt) * sizeof(fd_exec_test_acct_state_t)); + instr_context->accounts = fd_spad_alloc( txn_ctx->spad, alignof(fd_exec_test_acct_state_t), (instr_context->accounts_count + num_sysvar_entries + txn_ctx->executable_cnt) * sizeof(fd_exec_test_acct_state_t)); for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) { // Copy account information over fd_borrowed_account_t const * borrowed_account = &txn_ctx->borrowed_accounts[i]; fd_exec_test_acct_state_t * output_account = &instr_context->accounts[i]; - dump_account_state( borrowed_account, output_account ); + dump_account_state( borrowed_account, output_account, txn_ctx->spad ); } /* Add sysvar cache variables */ @@ -400,7 +406,7 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * // Copy it into output if (!account_exists) { fd_exec_test_acct_state_t * output_account = &instr_context->accounts[instr_context->accounts_count++]; - dump_account_state( borrowed_account, output_account ); + dump_account_state( borrowed_account, output_account, txn_ctx->spad ); } } @@ -422,13 +428,13 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * // Copy it into output if( !account_exists ) { fd_exec_test_acct_state_t * output_account = &instr_context->accounts[instr_context->accounts_count++]; - dump_account_state( borrowed_account, output_account ); + dump_account_state( borrowed_account, output_account, txn_ctx->spad ); } } /* Instruction Accounts */ instr_context->instr_accounts_count = (pb_size_t) instr->acct_cnt; - instr_context->instr_accounts = fd_scratch_alloc( alignof(fd_exec_test_instr_acct_t), instr_context->instr_accounts_count * sizeof(fd_exec_test_instr_acct_t) ); + instr_context->instr_accounts = fd_spad_alloc( txn_ctx->spad, alignof(fd_exec_test_instr_acct_t), instr_context->instr_accounts_count * sizeof(fd_exec_test_instr_acct_t) ); for( ushort i = 0; i < instr->acct_cnt; i++ ) { fd_exec_test_instr_acct_t * output_instr_account = &instr_context->instr_accounts[i]; @@ -442,7 +448,7 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * } /* Data */ - instr_context->data = fd_scratch_alloc( alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE(instr->data_sz) ); + instr_context->data = fd_spad_alloc( txn_ctx->spad, alignof(pb_bytes_array_t), PB_BYTES_ARRAY_T_ALLOCSIZE( instr->data_sz ) ); instr_context->data->size = (pb_size_t) instr->data_sz; fd_memcpy( instr_context->data->bytes, instr->data, instr->data_sz ); @@ -455,7 +461,7 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * /* Epoch Context */ instr_context->has_epoch_context = true; instr_context->epoch_context.has_features = true; - dump_sorted_features( &txn_ctx->epoch_ctx->features, &instr_context->epoch_context.features ); + dump_sorted_features( &txn_ctx->epoch_ctx->features, &instr_context->epoch_context.features, txn_ctx->spad ); } /***** PUBLIC APIs *****/ @@ -464,7 +470,7 @@ void fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fd_instr_info_t * instr, ushort instruction_idx ) { - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( txn_ctx->spad ) { // Get base58-encoded tx signature const fd_ed25519_sig_t * signatures = fd_txn_get_signatures( txn_ctx->txn_descriptor, txn_ctx->_txn_raw->raw ); fd_ed25519_sig_t signature; fd_memcpy( signature, signatures[0], sizeof(fd_ed25519_sig_t) ); @@ -486,7 +492,7 @@ fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, /* Output to file */ ulong out_buf_size = 100 * 1024 * 1024; - uint8_t * out = fd_scratch_alloc( alignof(uchar) , out_buf_size ); + uint8_t * out = fd_spad_alloc( txn_ctx->spad, alignof(uchar) , out_buf_size ); pb_ostream_t stream = pb_ostream_from_buffer( out, out_buf_size ); if (pb_encode(&stream, FD_EXEC_TEST_INSTR_CONTEXT_FIELDS, &instr_context)) { char output_filepath[256]; fd_memset(output_filepath, 0, sizeof(output_filepath)); @@ -505,12 +511,12 @@ fd_dump_instr_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fclose( file ); } } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } void fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fd_spad_t * spad ) { - FD_SCRATCH_SCOPE_BEGIN { + FD_SPAD_FRAME_BEGIN( spad ) { // Get base58-encoded tx signature const fd_ed25519_sig_t * signatures = fd_txn_get_signatures( txn_ctx->txn_descriptor, txn_ctx->_txn_raw->raw ); fd_ed25519_sig_t signature; fd_memcpy( signature, signatures[0], sizeof(fd_ed25519_sig_t) ); @@ -530,7 +536,7 @@ fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fd_spad_t * spad ) { /* Output to file */ ulong out_buf_size = 100 * 1024 * 1024; - uint8_t * out = fd_scratch_alloc( alignof(uint8_t), out_buf_size ); + uint8_t * out = fd_spad_alloc( spad, alignof(uint8_t), out_buf_size ); pb_ostream_t stream = pb_ostream_from_buffer( out, out_buf_size ); if( pb_encode( &stream, FD_EXEC_TEST_TXN_CONTEXT_FIELDS, &txn_context_msg ) ) { char output_filepath[256]; fd_memset( output_filepath, 0, sizeof(output_filepath) ); @@ -547,7 +553,7 @@ fd_dump_txn_to_protobuf( fd_exec_txn_ctx_t * txn_ctx, fd_spad_t * spad ) { fclose( file ); } } - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } @@ -591,17 +597,17 @@ fd_dump_vm_cpi_state( fd_vm_t * vm, sys_ctx.vm_ctx.heap_max = vm->heap_max; /* should be equiv. to txn_ctx->heap_sz */ - FD_SCRATCH_SCOPE_BEGIN{ - sys_ctx.vm_ctx.rodata = fd_scratch_alloc( 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE(vm->rodata_sz) ); + FD_SPAD_FRAME_BEGIN( vm->instr_ctx->txn_ctx->spad ) { + sys_ctx.vm_ctx.rodata = fd_spad_alloc( vm->instr_ctx->txn_ctx->spad, 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE( vm->rodata_sz ) ); sys_ctx.vm_ctx.rodata->size = (pb_size_t) vm->rodata_sz; fd_memcpy( sys_ctx.vm_ctx.rodata->bytes, vm->rodata, vm->rodata_sz ); pb_size_t stack_sz = (pb_size_t) ( (vm->frame_cnt + 1)*FD_VM_STACK_GUARD_SZ*2 ); - sys_ctx.syscall_invocation.stack_prefix = fd_scratch_alloc( 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE(stack_sz) ); + sys_ctx.syscall_invocation.stack_prefix = fd_spad_alloc( vm->instr_ctx->txn_ctx->spad, 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE( stack_sz ) ); sys_ctx.syscall_invocation.stack_prefix->size = stack_sz; fd_memcpy( sys_ctx.syscall_invocation.stack_prefix->bytes, vm->stack, stack_sz ); - sys_ctx.syscall_invocation.heap_prefix = fd_scratch_alloc( 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE(vm->heap_max) ); + sys_ctx.syscall_invocation.heap_prefix = fd_spad_alloc( vm->instr_ctx->txn_ctx->spad, 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE( vm->heap_max ) ); sys_ctx.syscall_invocation.heap_prefix->size = (pb_size_t) vm->instr_ctx->txn_ctx->heap_size; fd_memcpy( sys_ctx.syscall_invocation.heap_prefix->bytes, vm->heap, vm->instr_ctx->txn_ctx->heap_size ); @@ -641,5 +647,5 @@ fd_dump_vm_cpi_state( fd_vm_t * vm, fclose(f); - } FD_SCRATCH_SCOPE_END; + } FD_SPAD_FRAME_END; } diff --git a/src/flamenco/runtime/tests/run_ledger_tests_all.txt b/src/flamenco/runtime/tests/run_ledger_tests_all.txt index ddf4ded74b..3da4bfcf5d 100644 --- a/src/flamenco/runtime/tests/run_ledger_tests_all.txt +++ b/src/flamenco/runtime/tests/run_ledger_tests_all.txt @@ -84,4 +84,5 @@ src/flamenco/runtime/tests/run_ledger_test.sh -l testnet-307395181 -s snapshot-3 src/flamenco/runtime/tests/run_ledger_test.sh -l mainnet-308392063 -s snapshot-308392062-FDuB6CFKod14xGRGmdiRpQx2uaKyp3GDkyai2Ba7eH8d.tar.zst -p 60 -y 16 -m 5000000 -e 308392090 -c 2.0.18 src/flamenco/runtime/tests/run_ledger_test.sh -l devnet-350814254 -s snapshot-350814253-G5P3eNtkWUGkZ8b871wvf6d78wYxBJp637PCWJuQByZa.tar.zst -p 60 -y 16 -m 5000000 -e 350814284 -c 2.0.15 src/flamenco/runtime/tests/run_ledger_test.sh -l testnet-311586340 -s snapshot-311586340-13GSzvNzfBcz1KX6xBs55A8EKNWnCCRZ5Z84T1MSnuUm.tar.zst -p 60 -y 16 -m 5000000 -e 311586380 -c 2.1.1 -src/flamenco/runtime/tests/run_ledger_test.sh -l v213-transaction-loading-failure-fees -s snapshot-840-FJJdBrTQDbqE6uCAd8TBAxN4Gx3BQEPjbd8owb4vEn8W.tar.zst -p 60 -y 16 -m 5000000 -e 850 -c 2.1.13 -o PaymEPK2oqwT9TXAVfadjztH2H6KfLEB9Hhd5Q5frvP \ No newline at end of file +src/flamenco/runtime/tests/run_ledger_test.sh -l v213-transaction-loading-failure-fees -s snapshot-840-FJJdBrTQDbqE6uCAd8TBAxN4Gx3BQEPjbd8owb4vEn8W.tar.zst -p 60 -y 16 -m 5000000 -e 850 -c 2.1.13 -o PaymEPK2oqwT9TXAVfadjztH2H6KfLEB9Hhd5Q5frvP +src/flamenco/runtime/tests/run_ledger_test.sh -l reserve-minimal-cus-for-builtins -s snapshot-100-88Gt4ikriNfwToXqzdKj4jVcFoKGVzx6sqyszBftBF87.tar.zst -p 60 -y 16 -m 5000000 -e 850 -c 2.1.13 -o C9oAhLxDBm3ssWtJx1yBGzPY55r2rArHmN1pbQn6HogH