From 7b95c8e698e12ec8d2c96d3c75186a089fbe2da5 Mon Sep 17 00:00:00 2001 From: Tao Zhu <82401714+taozhu-chicago@users.noreply.github.com> Date: Fri, 10 Mar 2023 14:02:24 -0600 Subject: [PATCH] add default_cost as mandatory field for Builtin (#30639) * add default_cost as mandatory field for Builtin * updated tests * set zkp program default to VerifyTransfer CUs --------- Co-authored-by: Jon Cinque --- ledger/src/builtins.rs | 2 +- program-runtime/src/invoke_context.rs | 11 +- program-test/src/lib.rs | 13 +- programs/bpf_loader/src/deprecated.rs | 1 + programs/bpf_loader/src/lib.rs | 3 +- programs/bpf_loader/src/upgradeable.rs | 1 + .../bpf_loader/src/upgradeable_with_jit.rs | 1 + programs/bpf_loader/src/with_jit.rs | 3 +- programs/sbf/benches/bpf_loader.rs | 4 +- programs/sbf/tests/programs.rs | 144 +++++++++--------- runtime/benches/bank.rs | 1 + runtime/src/bank.rs | 15 +- runtime/src/bank/tests.rs | 73 ++++++--- runtime/src/builtins.rs | 24 ++- runtime/src/message_processor.rs | 3 + sdk/src/builtins.rs | 21 ++- 16 files changed, 208 insertions(+), 112 deletions(-) diff --git a/ledger/src/builtins.rs b/ledger/src/builtins.rs index d8a9ffa37e..e7a5d0618d 100644 --- a/ledger/src/builtins.rs +++ b/ledger/src/builtins.rs @@ -2,7 +2,7 @@ use solana_runtime::builtins::{Builtin, BuiltinFeatureTransition, Builtins}; macro_rules! to_builtin { ($b:expr) => { - Builtin::new(&$b.0, $b.1, $b.2) + Builtin::new(&$b.0, $b.1, $b.2, $b.3) }; } diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 17904dd02f..4be8f1a191 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -43,6 +43,7 @@ pub type ProcessInstructionWithContext = fn(&mut InvokeContext) -> Result<(), In pub struct BuiltinProgram { pub program_id: Pubkey, pub process_instruction: ProcessInstructionWithContext, + pub default_compute_unit_cost: u64, } impl std::fmt::Debug for BuiltinProgram { @@ -55,7 +56,11 @@ impl std::fmt::Debug for BuiltinProgram { // https://github.com/rust-lang/rust/issues/50280 // https://users.rust-lang.org/t/display-function-pointer/17073/2 let erased_instruction: ErasedProcessInstructionWithContext = self.process_instruction; - write!(f, "{}: {:p}", self.program_id, erased_instruction) + write!( + f, + "{}: {:p} CUs: {}", + self.program_id, erased_instruction, self.default_compute_unit_cost + ) } } @@ -1073,10 +1078,12 @@ mod tests { BuiltinProgram { program_id: solana_sdk::pubkey::new_rand(), process_instruction: mock_process_instruction, + default_compute_unit_cost: 0, }, BuiltinProgram { program_id: solana_sdk::pubkey::new_rand(), process_instruction: mock_ix_processor, + default_compute_unit_cost: 0, }, ]; assert!(!format!("{builtin_programs:?}").is_empty()); @@ -1262,6 +1269,7 @@ mod tests { let builtin_programs = &[BuiltinProgram { program_id: callee_program_id, process_instruction: mock_process_instruction, + default_compute_unit_cost: 0, }]; let owned_account = AccountSharedData::new(42, 1, &callee_program_id); @@ -1420,6 +1428,7 @@ mod tests { let builtin_programs = [BuiltinProgram { program_id: program_key, process_instruction: mock_process_instruction, + default_compute_unit_cost: 0, }]; let mut transaction_context = diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index 304bf46383..d81fb43b54 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -622,7 +622,7 @@ impl ProgramTest { let add_native = |this: &mut ProgramTest, process_fn: ProcessInstructionWithContext| { info!("\"{}\" program loaded as native code", program_name); this.builtins - .push(Builtin::new(program_name, program_id, process_fn)); + .push(Builtin::new(program_name, program_id, process_fn, 0)); }; let warn_invalid_program_name = || { @@ -695,8 +695,12 @@ impl ProgramTest { process_instruction: ProcessInstructionWithContext, ) { info!("\"{}\" builtin program", program_name); - self.builtins - .push(Builtin::new(program_name, program_id, process_instruction)); + self.builtins.push(Builtin::new( + program_name, + program_id, + process_instruction, + 0, + )); } /// Deactivate a runtime feature. @@ -789,7 +793,7 @@ impl ProgramTest { // Add loaders macro_rules! add_builtin { ($b:expr) => { - bank.add_builtin(&$b.0, &$b.1, $b.2) + bank.add_builtin(&$b.0, &$b.1, $b.2, $b.3) }; } add_builtin!(solana_bpf_loader_deprecated_program!()); @@ -812,6 +816,7 @@ impl ProgramTest { &builtin.name, &builtin.id, builtin.process_instruction_with_context, + 0, ); } diff --git a/programs/bpf_loader/src/deprecated.rs b/programs/bpf_loader/src/deprecated.rs index 3c1ee26602..212061d9dd 100644 --- a/programs/bpf_loader/src/deprecated.rs +++ b/programs/bpf_loader/src/deprecated.rs @@ -2,5 +2,6 @@ solana_sdk::declare_builtin!( solana_sdk::bpf_loader_deprecated::ID, solana_bpf_loader_deprecated_program, solana_bpf_loader_program::process_instruction, + 1140, deprecated::id ); diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index b3227429ca..94477c8096 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -75,7 +75,8 @@ use { solana_sdk::declare_builtin!( solana_sdk::bpf_loader::ID, solana_bpf_loader_program, - solana_bpf_loader_program::process_instruction + solana_bpf_loader_program::process_instruction, + 570 ); /// Errors returned by functions the BPF Loader registers with the VM diff --git a/programs/bpf_loader/src/upgradeable.rs b/programs/bpf_loader/src/upgradeable.rs index 89aaed9fb5..995fac3fad 100644 --- a/programs/bpf_loader/src/upgradeable.rs +++ b/programs/bpf_loader/src/upgradeable.rs @@ -2,5 +2,6 @@ solana_sdk::declare_builtin!( solana_sdk::bpf_loader_upgradeable::ID, solana_bpf_loader_upgradeable_program, solana_bpf_loader_program::process_instruction, + 2370, upgradeable::id ); diff --git a/programs/bpf_loader/src/upgradeable_with_jit.rs b/programs/bpf_loader/src/upgradeable_with_jit.rs index da479a400a..c063303d33 100644 --- a/programs/bpf_loader/src/upgradeable_with_jit.rs +++ b/programs/bpf_loader/src/upgradeable_with_jit.rs @@ -2,5 +2,6 @@ solana_sdk::declare_builtin!( solana_sdk::bpf_loader_upgradeable::ID, solana_bpf_loader_upgradeable_program_with_jit, solana_bpf_loader_program::process_instruction_jit, + 2370, upgradeable_with_jit::id ); diff --git a/programs/bpf_loader/src/with_jit.rs b/programs/bpf_loader/src/with_jit.rs index 43aafc690c..a13d8e6d99 100644 --- a/programs/bpf_loader/src/with_jit.rs +++ b/programs/bpf_loader/src/with_jit.rs @@ -1,5 +1,6 @@ solana_sdk::declare_builtin!( solana_sdk::bpf_loader::ID, solana_bpf_loader_program_with_jit, - solana_bpf_loader_program::process_instruction_jit + solana_bpf_loader_program::process_instruction_jit, + 570 ); diff --git a/programs/sbf/benches/bpf_loader.rs b/programs/sbf/benches/bpf_loader.rs index 508de137c3..5e0a8b5f8c 100644 --- a/programs/sbf/benches/bpf_loader.rs +++ b/programs/sbf/benches/bpf_loader.rs @@ -159,8 +159,8 @@ fn bench_program_execute_noop(bencher: &mut Bencher) { .. } = create_genesis_config(50); let mut bank = Bank::new_for_benches(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index e5ce5a7651..bda6aeabd4 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -432,8 +432,8 @@ fn test_program_sbf_sanity() { } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); // Call user program @@ -480,8 +480,8 @@ fn test_program_sbf_loader_deprecated() { .remove(&solana_sdk::feature_set::disable_deploy_of_alloc_free_syscall::id()) .unwrap(); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_deprecated_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_deprecated_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let program_id = create_program(&bank, &bpf_loader_deprecated::id(), program); let bank_client = BankClient::new(bank); @@ -507,8 +507,8 @@ fn test_sol_alloc_free_no_longer_deployable() { } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); // Populate loader account with elf that depends on _sol_alloc_free syscall let elf = load_program_from_file("solana_sbf_rust_deprecated_loader"); @@ -600,8 +600,8 @@ fn test_program_sbf_duplicate_accounts() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); let program_id = load_program(&bank_client, &bpf_loader::id(), &mint_keypair, program); @@ -701,8 +701,8 @@ fn test_program_sbf_error_handling() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let program_id = load_program(&bank_client, &bpf_loader::id(), &mint_keypair, program); let account_metas = vec![AccountMeta::new(mint_keypair.pubkey(), true)]; @@ -803,8 +803,8 @@ fn test_return_data_and_log_data_syscall() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -868,8 +868,8 @@ fn test_program_sbf_invoke_sanity() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1265,8 +1265,8 @@ fn test_program_sbf_program_id_spoofing() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1318,8 +1318,8 @@ fn test_program_sbf_caller_has_access_to_cpi_program() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1358,8 +1358,8 @@ fn test_program_sbf_ro_modify() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1415,8 +1415,8 @@ fn test_program_sbf_call_depth() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let program_id = load_program( &bank_client, @@ -1450,8 +1450,8 @@ fn test_program_sbf_compute_budget() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let program_id = load_program( &bank_client, @@ -1549,8 +1549,8 @@ fn test_program_sbf_instruction_introspection() { } = create_genesis_config(50_000); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1609,8 +1609,8 @@ fn test_program_sbf_test_use_latest_executor() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let panic_id = load_program( &bank_client, @@ -1678,8 +1678,8 @@ fn test_program_sbf_upgrade() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); // Deploy upgrade program @@ -1770,8 +1770,8 @@ fn test_program_sbf_invoke_in_same_tx_as_deployment() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1866,8 +1866,8 @@ fn test_program_sbf_invoke_in_same_tx_as_redeployment() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -1970,8 +1970,8 @@ fn test_program_sbf_invoke_in_same_tx_as_undeployment() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -2059,10 +2059,10 @@ fn test_program_sbf_invoke_upgradeable_via_cpi() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let invoke_and_return = load_program( &bank_client, @@ -2177,8 +2177,8 @@ fn test_program_sbf_disguised_as_sbf_loader() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let program_id = load_program(&bank_client, &bpf_loader::id(), &mint_keypair, program); @@ -2203,8 +2203,8 @@ fn test_program_sbf_c_dup() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let account_address = Pubkey::new_unique(); let account = AccountSharedData::new_data(42, &[1_u8, 2, 3], &system_program::id()).unwrap(); @@ -2234,10 +2234,10 @@ fn test_program_sbf_upgrade_via_cpi() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let invoke_and_return = load_program( &bank_client, @@ -2341,10 +2341,10 @@ fn test_program_sbf_set_upgrade_authority_via_cpi() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); // Deploy CPI invoker program @@ -2434,8 +2434,8 @@ fn test_program_upgradeable_locks() { .. } = create_genesis_config(2_000_000_000); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_upgradeable_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -2555,8 +2555,8 @@ fn test_program_sbf_finalize() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -2601,8 +2601,8 @@ fn test_program_sbf_ro_account_modify() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -2668,8 +2668,8 @@ fn test_program_sbf_realloc() { let signer = &[&mint_keypair]; let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -2965,8 +2965,8 @@ fn test_program_sbf_realloc_invoke() { let signer = &[&mint_keypair]; let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -3483,8 +3483,8 @@ fn test_program_sbf_processed_inner_instruction() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -3567,8 +3567,8 @@ fn test_program_fees() { bank.fee_structure = fee_structure.clone(); bank.feature_set = Arc::new(FeatureSet::all_enabled()); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank_client = BankClient::new(bank); let program_id = load_program( @@ -3640,8 +3640,8 @@ fn test_get_minimum_delegation() { let mut bank = Bank::new_for_tests(&genesis_config); bank.feature_set = Arc::new(FeatureSet::all_enabled()); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -3669,10 +3669,10 @@ fn test_program_sbf_inner_instruction_alignment_checks() { .. } = create_genesis_config(50); let mut bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - bank.add_builtin(&name, &id, entrypoint); - let (name, id, entrypoint) = solana_bpf_loader_deprecated_program!(); - bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); + let (name, id, entrypoint, cost) = solana_bpf_loader_deprecated_program!(); + bank.add_builtin(&name, &id, entrypoint, cost); let noop = create_program(&bank, &bpf_loader_deprecated::id(), "solana_sbf_rust_noop"); let inner_instruction_alignment_check = create_program( &bank, diff --git a/runtime/benches/bank.rs b/runtime/benches/bank.rs index 91fd305f06..43175096bd 100644 --- a/runtime/benches/bank.rs +++ b/runtime/benches/bank.rs @@ -136,6 +136,7 @@ fn do_bench_transactions( "builtin_program", &Pubkey::from(BUILTIN_PROGRAM_ID), process_instruction, + 0, ); bank.add_builtin_account("solana_noop_program", &Pubkey::from(NOOP_PROGRAM_ID), false); let bank = Arc::new(bank); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 1676e5945a..26074e4762 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -6577,6 +6577,7 @@ impl Bank { &builtin.name, &builtin.id, builtin.process_instruction_with_context, + builtin.default_compute_unit_cost, ); } for precompile in get_precompiles() { @@ -7521,8 +7522,12 @@ impl Bank { name: &str, program_id: &Pubkey, process_instruction: ProcessInstructionWithContext, + default_compute_unit_cost: u64, ) { - debug!("Adding program {} under {:?}", name, program_id); + debug!( + "Adding program {} under {:?} default_compute_unit_cost {}", + name, program_id, default_compute_unit_cost + ); self.add_builtin_account(name, program_id, false); if let Some(entry) = self .builtin_programs @@ -7531,13 +7536,18 @@ impl Bank { .find(|entry| entry.program_id == *program_id) { entry.process_instruction = process_instruction; + entry.default_compute_unit_cost = default_compute_unit_cost; } else { self.builtin_programs.vec.push(BuiltinProgram { program_id: *program_id, process_instruction, + default_compute_unit_cost, }); } - debug!("Added program {} under {:?}", name, program_id); + debug!( + "Added program {} under {:?} default_compute_unit_cost {}", + name, program_id, default_compute_unit_cost + ); } /// Remove a builtin instruction processor if it already exists @@ -7805,6 +7815,7 @@ impl Bank { &builtin.name, &builtin.id, builtin.process_instruction_with_context, + builtin.default_compute_unit_cost, ), BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id), } diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 64f2174981..e2b93ca124 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -1377,7 +1377,12 @@ fn test_rent_complex() { root_bank.restore_old_behavior_for_fragile_tests(); let root_bank = Arc::new(root_bank); let mut bank = create_child_bank_for_rent_test(&root_bank, &genesis_config); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin( + "mock_program", + &mock_program_id, + mock_process_instruction, + 0, + ); assert_eq!(bank.last_blockhash(), genesis_config.hash()); @@ -5083,6 +5088,7 @@ fn test_add_builtin() { "mock_vote_program", &mock_vote_program_id(), mock_vote_processor, + 0, ); assert!(bank.get_account(&mock_vote_program_id()).is_some()); @@ -5154,6 +5160,7 @@ fn test_add_duplicate_static_program() { "solana_vote_program", &solana_vote_program::id(), mock_vote_processor, + 0, ); let new_vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap(); // Vote loader account should not be updated since it was included in the genesis config. @@ -5207,8 +5214,8 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() { continue; } - bank.add_builtin("mock_program1", &vote_id, mock_ix_processor); - bank.add_builtin("mock_program2", &stake_id, mock_ix_processor); + bank.add_builtin("mock_program1", &vote_id, mock_ix_processor, 0); + bank.add_builtin("mock_program2", &stake_id, mock_ix_processor, 0); { let stakes = bank.stakes_cache.stakes(); assert!(stakes.vote_accounts().as_ref().is_empty()); @@ -5231,8 +5238,8 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() { // Re-adding builtin programs should be no-op bank.update_accounts_hash_for_tests(); let old_hash = bank.get_accounts_hash().unwrap(); - bank.add_builtin("mock_program1", &vote_id, mock_ix_processor); - bank.add_builtin("mock_program2", &stake_id, mock_ix_processor); + bank.add_builtin("mock_program1", &vote_id, mock_ix_processor, 0); + bank.add_builtin("mock_program2", &stake_id, mock_ix_processor, 0); add_root_and_flush_write_cache(&bank); bank.update_accounts_hash_for_tests(); let new_hash = bank.get_accounts_hash().unwrap(); @@ -6485,7 +6492,12 @@ fn test_transaction_with_duplicate_accounts_in_instruction() { } let mock_program_id = Pubkey::from([2u8; 32]); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin( + "mock_program", + &mock_program_id, + mock_process_instruction, + 0, + ); let from_pubkey = solana_sdk::pubkey::new_rand(); let to_pubkey = solana_sdk::pubkey::new_rand(); @@ -6528,7 +6540,12 @@ fn test_transaction_with_program_ids_passed_to_programs() { } let mock_program_id = Pubkey::from([2u8; 32]); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin( + "mock_program", + &mock_program_id, + mock_process_instruction, + 0, + ); let from_pubkey = solana_sdk::pubkey::new_rand(); let to_pubkey = solana_sdk::pubkey::new_rand(); @@ -6584,6 +6601,7 @@ fn test_account_ids_after_program_ids() { "mock_vote", &solana_vote_program::id(), mock_ok_vote_processor, + 0, ); let result = bank.process_transaction(&tx); assert_eq!(result, Ok(())); @@ -6638,6 +6656,7 @@ fn test_duplicate_account_key() { "mock_vote", &solana_vote_program::id(), mock_ok_vote_processor, + 0, ); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); @@ -6671,6 +6690,7 @@ fn test_process_transaction_with_too_many_account_locks() { "mock_vote", &solana_vote_program::id(), mock_ok_vote_processor, + 0, ); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); @@ -6708,6 +6728,7 @@ fn test_program_id_as_payer() { "mock_vote", &solana_vote_program::id(), mock_ok_vote_processor, + 0, ); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); @@ -6762,6 +6783,7 @@ fn test_ref_account_key_after_program_id() { "mock_vote", &solana_vote_program::id(), mock_ok_vote_processor, + 0, ); let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas); @@ -6793,7 +6815,7 @@ fn test_fuzz_instructions() { .map(|i| { let key = solana_sdk::pubkey::new_rand(); let name = format!("program{i:?}"); - bank.add_builtin(&name, &key, mock_ok_vote_processor); + bank.add_builtin(&name, &key, mock_ok_vote_processor, 0); (key, name.as_bytes().to_vec()) }) .collect(); @@ -7001,7 +7023,7 @@ fn test_same_program_id_uses_unqiue_executable_accounts() { // Add a new program let program1_pubkey = solana_sdk::pubkey::new_rand(); - bank.add_builtin("program", &program1_pubkey, nested_processor); + bank.add_builtin("program", &program1_pubkey, nested_processor, 0); // Add a new program owned by the first let program2_pubkey = solana_sdk::pubkey::new_rand(); @@ -7225,13 +7247,13 @@ fn test_add_builtin_no_overwrite() { Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &program_id, mock_ix_processor); + .add_builtin("mock_program", &program_id, mock_ix_processor, 0); assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot); let mut bank = Arc::new(new_from_parent(&bank)); Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &program_id, mock_ix_processor); + .add_builtin("mock_program", &program_id, mock_ix_processor, 0); assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot); } @@ -7256,13 +7278,13 @@ fn test_add_builtin_loader_no_overwrite() { Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &loader_id, mock_ix_processor); + .add_builtin("mock_program", &loader_id, mock_ix_processor, 0); assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot); let mut bank = Arc::new(new_from_parent(&bank)); Arc::get_mut(&mut bank) .unwrap() - .add_builtin("mock_program", &loader_id, mock_ix_processor); + .add_builtin("mock_program", &loader_id, mock_ix_processor, 0); assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot); } @@ -7883,6 +7905,7 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { "solana_bpf_loader_upgradeable_program", &bpf_loader_upgradeable::id(), solana_bpf_loader_program::process_instruction, + 0, ); let bank = Arc::new(bank); let bank_client = BankClient::new_shared(&bank); @@ -10005,7 +10028,12 @@ fn test_tx_return_data() { Ok(()) } let blockhash = bank.last_blockhash(); - bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction); + bank.add_builtin( + "mock_program", + &mock_program_id, + mock_process_instruction, + 0, + ); for index in [ None, @@ -10196,7 +10224,7 @@ fn test_transfer_sysvar() { } let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program1", &program_id, mock_ix_processor); + bank.add_builtin("mock_program1", &program_id, mock_ix_processor, 0); let blockhash = bank.last_blockhash(); #[allow(deprecated)] @@ -10410,7 +10438,7 @@ fn test_compute_budget_program_noop() { Ok(()) } let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program", &program_id, mock_ix_processor); + bank.add_builtin("mock_program", &program_id, mock_ix_processor, 0); let message = Message::new( &[ @@ -10453,7 +10481,7 @@ fn test_compute_request_instruction() { Ok(()) } let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program", &program_id, mock_ix_processor); + bank.add_builtin("mock_program", &program_id, mock_ix_processor, 0); let message = Message::new( &[ @@ -10503,7 +10531,7 @@ fn test_failed_compute_request_instruction() { Ok(()) } let program_id = solana_sdk::pubkey::new_rand(); - bank.add_builtin("mock_program", &program_id, mock_ix_processor); + bank.add_builtin("mock_program", &program_id, mock_ix_processor, 0); // This message will not be executed because the compute budget request is invalid let message0 = Message::new( @@ -11134,6 +11162,7 @@ fn test_invalid_rent_state_changes_existing_accounts() { "mock_program", &mock_program_id, mock_transfer_process_instruction, + 0, ); let recent_blockhash = bank.last_blockhash(); @@ -11221,6 +11250,7 @@ fn test_invalid_rent_state_changes_new_accounts() { "mock_program", &mock_program_id, mock_transfer_process_instruction, + 0, ); let recent_blockhash = bank.last_blockhash(); @@ -11284,6 +11314,7 @@ fn test_drained_created_account() { "mock_program", &mock_program_id, mock_transfer_process_instruction, + 0, ); let recent_blockhash = bank.last_blockhash(); @@ -11939,6 +11970,7 @@ fn test_resize_and_rent() { "mock_realloc_program", &mock_program_id, mock_realloc_process_instruction, + 0, ); let recent_blockhash = bank.last_blockhash(); @@ -12214,6 +12246,7 @@ fn test_accounts_data_size_and_resize_transactions() { "mock_realloc_program", &mock_program_id, mock_realloc_process_instruction, + 0, ); let recent_blockhash = bank.last_blockhash(); @@ -12757,8 +12790,8 @@ fn test_runtime_feature_enable_with_executor_cache() { .accounts .remove(&feature_set::reject_callx_r10::id()); let mut root_bank = Bank::new_for_tests(&genesis_config); - let (name, id, entrypoint) = solana_bpf_loader_program!(); - root_bank.add_builtin(&name, &id, entrypoint); + let (name, id, entrypoint, cost) = solana_bpf_loader_program!(); + root_bank.add_builtin(&name, &id, entrypoint, cost); // Test a basic transfer let amount = genesis_config.rent.minimum_balance(0); diff --git a/runtime/src/builtins.rs b/runtime/src/builtins.rs index 045d4da840..3eddb17914 100644 --- a/runtime/src/builtins.rs +++ b/runtime/src/builtins.rs @@ -12,6 +12,11 @@ pub struct Builtin { pub name: String, pub id: Pubkey, pub process_instruction_with_context: ProcessInstructionWithContext, + // compute units to deduct from transaction's compute budget if builtin + // does not consume actual units during process_instruction. No builtin + // manually consumes units as bpf does (as of v1.16), but they could + // in the future. + pub default_compute_unit_cost: u64, } impl Builtin { @@ -19,18 +24,24 @@ impl Builtin { name: &str, id: Pubkey, process_instruction_with_context: ProcessInstructionWithContext, + default_compute_unit_cost: u64, ) -> Self { Self { name: name.to_string(), id, process_instruction_with_context, + default_compute_unit_cost, } } } impl fmt::Debug for Builtin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Builtin [name={}, id={}]", self.name, self.id) + write!( + f, + "Builtin [name={}, id={}, default_compute_unit_cost={}]", + self.name, self.id, self.default_compute_unit_cost + ) } } @@ -41,6 +52,7 @@ impl AbiExample for Builtin { name: String::default(), id: Pubkey::default(), process_instruction_with_context: |_invoke_context| Ok(()), + default_compute_unit_cost: u64::default(), } } } @@ -120,21 +132,25 @@ fn genesis_builtins() -> Vec { "system_program", system_program::id(), system_instruction_processor::process_instruction, + 150, ), Builtin::new( "vote_program", solana_vote_program::id(), solana_vote_program::vote_processor::process_instruction, + 2100, ), Builtin::new( "stake_program", stake::program::id(), solana_stake_program::stake_instruction::process_instruction, + 750, ), Builtin::new( "config_program", solana_config_program::id(), solana_config_program::config_processor::process_instruction, + 450, ), ] } @@ -147,6 +163,7 @@ fn builtin_feature_transitions() -> Vec { "compute_budget_program", solana_sdk::compute_budget::id(), solana_compute_budget_program::process_instruction, + 150, ), feature_id: feature_set::add_compute_budget_program::id(), }, @@ -155,6 +172,7 @@ fn builtin_feature_transitions() -> Vec { "address_lookup_table_program", solana_address_lookup_table_program::id(), solana_address_lookup_table_program::processor::process_instruction, + 750, ), feature_id: feature_set::versioned_tx_message_enabled::id(), }, @@ -163,6 +181,10 @@ fn builtin_feature_transitions() -> Vec { "zk_token_proof_program", solana_zk_token_sdk::zk_token_proof_program::id(), solana_zk_token_proof_program::process_instruction, + 219_290, // zk proof program CU per instruction were sampled here: + // https://github.com/solana-labs/solana/pull/30639 + // Picking `VerifyTransfer`'s CU as program default + // because it is the most used instruction. ), feature_id: feature_set::zk_token_sdk_enabled::id(), }, diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 1a2e20048b..177d5e5521 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -255,6 +255,7 @@ mod tests { let builtin_programs = &[BuiltinProgram { program_id: mock_system_program_id, process_instruction: mock_system_process_instruction, + default_compute_unit_cost: 0, }]; let accounts = vec![ @@ -484,6 +485,7 @@ mod tests { let builtin_programs = &[BuiltinProgram { program_id: mock_program_id, process_instruction: mock_system_process_instruction, + default_compute_unit_cost: 0, }]; let accounts = vec![ @@ -649,6 +651,7 @@ mod tests { let builtin_programs = &[BuiltinProgram { program_id: mock_program_id, process_instruction: mock_process_instruction, + default_compute_unit_cost: 0, }]; let mut secp256k1_account = AccountSharedData::new(1, 0, &native_loader::id()); diff --git a/sdk/src/builtins.rs b/sdk/src/builtins.rs index e837abcdb2..af2e593ae3 100644 --- a/sdk/src/builtins.rs +++ b/sdk/src/builtins.rs @@ -3,7 +3,7 @@ #[rustversion::since(1.46.0)] #[macro_export] macro_rules! declare_builtin_name { - ($name:ident, $id:path, $entrypoint:expr) => { + ($name:ident, $id:path, $entrypoint:expr, $default_cost:expr) => { #[macro_export] macro_rules! $name { () => { @@ -39,6 +39,7 @@ macro_rules! declare_builtin_name { stringify!($name).to_string(), ::solana_sdk::respan!($crate::$id, $name)(), $entrypoint, + $default_cost, ) }; } @@ -48,11 +49,16 @@ macro_rules! declare_builtin_name { #[rustversion::not(since(1.46.0))] #[macro_export] macro_rules! declare_builtin_name { - ($name:ident, $id:path, $entrypoint:expr) => { + ($name:ident, $id:path, $entrypoint:expr, $default_cost:expr) => { #[macro_export] macro_rules! $name { () => { - (stringify!($name).to_string(), $crate::$id(), $entrypoint) + ( + stringify!($name).to_string(), + $crate::$id(), + $entrypoint, + $default_cost, + ) }; } }; @@ -63,15 +69,16 @@ macro_rules! declare_builtin_name { /// bs58_string: bs58 string representation the program's id /// name: Name of the program /// entrypoint: Program's entrypoint, must be of `type Entrypoint` +/// default_cost: Program's default compute units /// id: Path to the program id access function, used if this macro is not /// called in `src/lib` #[macro_export] macro_rules! declare_builtin { - ($bs58_string:expr, $name:ident, $entrypoint:expr) => { - $crate::declare_builtin!($bs58_string, $name, $entrypoint, id); + ($bs58_string:expr, $name:ident, $entrypoint:expr, $default_cost:expr) => { + $crate::declare_builtin!($bs58_string, $name, $entrypoint, $default_cost, id); }; - ($bs58_string:expr, $name:ident, $entrypoint:expr, $id:path) => { + ($bs58_string:expr, $name:ident, $entrypoint:expr, $default_cost:expr, $id:path) => { $crate::declare_id!($bs58_string); - $crate::declare_builtin_name!($name, $id, $entrypoint); + $crate::declare_builtin_name!($name, $id, $entrypoint, $default_cost); }; }