From ad9fceec8e072ae3cef2831ed4d8823990e4e61e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 7 Feb 2022 05:11:14 +0000 Subject: [PATCH] Update syscall base costs (#22930) (cherry picked from commit 2aa113fd8ce6590735dcb63f3ed84029d48f99ab) Co-authored-by: Dmitri Makarov --- programs/bpf_loader/src/syscalls.rs | 97 ++++++++++++++++++++++++----- sdk/src/feature_set.rs | 5 ++ sdk/src/process_instruction.rs | 3 + 3 files changed, 89 insertions(+), 16 deletions(-) diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 3e9e2cf5ae..344ce2775e 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -23,7 +23,7 @@ use { libsecp256k1_0_5_upgrade_enabled, mem_overlap_fix, memory_ops_syscalls, return_data_syscall_enabled, secp256k1_recover_syscall_enabled, set_upgrade_authority_via_cpi_enabled, sol_log_data_syscall_enabled, - sysvar_via_syscall, update_data_on_realloc, + sysvar_via_syscall, update_data_on_realloc, update_syscall_base_costs, }, hash::{Hasher, HASH_BYTES}, ic_msg, @@ -225,6 +225,8 @@ pub fn bind_syscall_context_objects<'a>( compute_meter: invoke_context.get_compute_meter(), loader_id, enforce_aligned_host_addrs, + update_syscall_base_costs: invoke_context + .is_feature_active(&update_syscall_base_costs::id()), }), None, )?; @@ -234,6 +236,9 @@ pub fn bind_syscall_context_objects<'a>( logger: invoke_context.get_logger(), loader_id, enforce_aligned_host_addrs, + cost: invoke_context.get_bpf_compute_budget().syscall_base_cost, + update_syscall_base_costs: invoke_context + .is_feature_active(&update_syscall_base_costs::id()), }), None, )?; @@ -248,7 +253,11 @@ pub fn bind_syscall_context_objects<'a>( vm.bind_syscall_context_object( Box::new(SyscallLogBpfComputeUnits { - cost: 0, + cost: if invoke_context.is_feature_active(&update_syscall_base_costs::id()) { + invoke_context.get_bpf_compute_budget().syscall_base_cost + } else { + 0 + }, compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), }), @@ -317,37 +326,49 @@ pub fn bind_syscall_context_objects<'a>( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemcpy { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + base_cost: invoke_context.get_bpf_compute_budget().mem_op_base_cost, + byte_cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, mem_overlap_fix: invoke_context.is_feature_active(&mem_overlap_fix::id()), + update_syscall_base_costs: invoke_context + .is_feature_active(&update_syscall_base_costs::id()), }), ); bind_feature_gated_syscall_context_object!( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemmove { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + base_cost: invoke_context.get_bpf_compute_budget().mem_op_base_cost, + byte_cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, + update_syscall_base_costs: invoke_context + .is_feature_active(&update_syscall_base_costs::id()), }), ); bind_feature_gated_syscall_context_object!( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemcmp { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + base_cost: invoke_context.get_bpf_compute_budget().mem_op_base_cost, + byte_cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, + update_syscall_base_costs: invoke_context + .is_feature_active(&update_syscall_base_costs::id()), }), ); bind_feature_gated_syscall_context_object!( vm, invoke_context.is_feature_active(&memory_ops_syscalls::id()), Box::new(SyscallMemset { - cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, + base_cost: invoke_context.get_bpf_compute_budget().mem_op_base_cost, + byte_cost: invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit, compute_meter: invoke_context.get_compute_meter(), loader_id, + update_syscall_base_costs: invoke_context + .is_feature_active(&update_syscall_base_costs::id()), }), ); @@ -645,6 +666,7 @@ pub struct SyscallPanic<'a> { compute_meter: Rc>, loader_id: &'a Pubkey, enforce_aligned_host_addrs: bool, + update_syscall_base_costs: bool, } impl<'a> SyscallObject for SyscallPanic<'a> { fn call( @@ -657,7 +679,9 @@ impl<'a> SyscallObject for SyscallPanic<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - question_mark!(self.compute_meter.consume(len), result); + if !self.update_syscall_base_costs { + question_mark!(self.compute_meter.consume(len), result); + } *result = translate_string_and_do( memory_mapping, file, @@ -675,6 +699,8 @@ pub struct SyscallLog<'a> { logger: Rc>, loader_id: &'a Pubkey, enforce_aligned_host_addrs: bool, + cost: u64, + update_syscall_base_costs: bool, } impl<'a> SyscallObject for SyscallLog<'a> { fn call( @@ -687,7 +713,12 @@ impl<'a> SyscallObject for SyscallLog<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - question_mark!(self.compute_meter.consume(len), result); + let cost = if self.update_syscall_base_costs { + self.cost.max(len) + } else { + len + }; + question_mark!(self.compute_meter.consume(cost), result); question_mark!( translate_string_and_do( memory_mapping, @@ -1354,10 +1385,12 @@ fn check_overlapping(src_addr: u64, dst_addr: u64, n: u64) -> bool { /// memcpy pub struct SyscallMemcpy<'a> { - cost: u64, + base_cost: u64, + byte_cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, mem_overlap_fix: bool, + update_syscall_base_costs: bool, } impl<'a> SyscallObject for SyscallMemcpy<'a> { fn call( @@ -1370,6 +1403,12 @@ impl<'a> SyscallObject for SyscallMemcpy<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { + let cost = if self.update_syscall_base_costs { + self.base_cost.max(n / self.byte_cost) + } else { + n / self.byte_cost + }; + question_mark!(self.compute_meter.consume(cost), result); if if self.mem_overlap_fix { check_overlapping(src_addr, dst_addr, n) } else { @@ -1379,7 +1418,6 @@ impl<'a> SyscallObject for SyscallMemcpy<'a> { return; } - question_mark!(self.compute_meter.consume(n / self.cost), result); let dst = question_mark!( translate_slice_mut::(memory_mapping, dst_addr, n, self.loader_id, true), result @@ -1396,9 +1434,11 @@ impl<'a> SyscallObject for SyscallMemcpy<'a> { } /// memmove pub struct SyscallMemmove<'a> { - cost: u64, + base_cost: u64, + byte_cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + update_syscall_base_costs: bool, } impl<'a> SyscallObject for SyscallMemmove<'a> { fn call( @@ -1411,7 +1451,12 @@ impl<'a> SyscallObject for SyscallMemmove<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - question_mark!(self.compute_meter.consume(n / self.cost), result); + let cost = if self.update_syscall_base_costs { + self.base_cost.max(n / self.byte_cost) + } else { + n / self.byte_cost + }; + question_mark!(self.compute_meter.consume(cost), result); let dst = question_mark!( translate_slice_mut::(memory_mapping, dst_addr, n, self.loader_id, true), result @@ -1428,9 +1473,11 @@ impl<'a> SyscallObject for SyscallMemmove<'a> { } /// memcmp pub struct SyscallMemcmp<'a> { - cost: u64, + base_cost: u64, + byte_cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + update_syscall_base_costs: bool, } impl<'a> SyscallObject for SyscallMemcmp<'a> { fn call( @@ -1443,7 +1490,12 @@ impl<'a> SyscallObject for SyscallMemcmp<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - question_mark!(self.compute_meter.consume(n / self.cost), result); + let cost = if self.update_syscall_base_costs { + self.base_cost.max(n / self.byte_cost) + } else { + n / self.byte_cost + }; + question_mark!(self.compute_meter.consume(cost), result); let s1 = question_mark!( translate_slice::(memory_mapping, s1_addr, n, self.loader_id, true), result @@ -1473,9 +1525,11 @@ impl<'a> SyscallObject for SyscallMemcmp<'a> { } /// memset pub struct SyscallMemset<'a> { - cost: u64, + base_cost: u64, + byte_cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + update_syscall_base_costs: bool, } impl<'a> SyscallObject for SyscallMemset<'a> { fn call( @@ -1488,7 +1542,12 @@ impl<'a> SyscallObject for SyscallMemset<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { - question_mark!(self.compute_meter.consume(n / self.cost), result); + let cost = if self.update_syscall_base_costs { + self.base_cost.max(n / self.byte_cost) + } else { + n / self.byte_cost + }; + question_mark!(self.compute_meter.consume(cost), result); let s = question_mark!( translate_slice_mut::(memory_mapping, s_addr, n, self.loader_id, true), result @@ -3153,6 +3212,7 @@ mod tests { compute_meter, loader_id: &bpf_loader::id(), enforce_aligned_host_addrs: true, + update_syscall_base_costs: true, }; let mut result: Result> = Ok(0); syscall_panic.call( @@ -3179,6 +3239,7 @@ mod tests { compute_meter, loader_id: &bpf_loader::id(), enforce_aligned_host_addrs: true, + update_syscall_base_costs: true, }; let mut result: Result> = Ok(0); syscall_panic.call( @@ -3208,6 +3269,8 @@ mod tests { logger, loader_id: &bpf_loader::id(), enforce_aligned_host_addrs: true, + cost: 100, + update_syscall_base_costs: true, }; let config = Config::default(); let memory_mapping = MemoryMapping::new::( @@ -3282,6 +3345,8 @@ mod tests { logger, loader_id: &bpf_loader::id(), enforce_aligned_host_addrs: true, + cost: string.len() as u64, + update_syscall_base_costs: true, }; let mut result: Result> = Ok(0); syscall_sol_log.call( diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index eec4f0b5b2..b7a7bbc94e 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -293,6 +293,10 @@ pub mod bank_tranaction_count_fix { solana_sdk::declare_id!("Vo5siZ442SaZBKPXNocthiXysNviW4UYPwRFggmbgAp"); } +pub mod update_syscall_base_costs { + solana_sdk::declare_id!("2h63t332mGCCsWK2nqqqHhN4U9ayyqhLVFvczznHDoTZ"); +} + lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -366,6 +370,7 @@ lazy_static! { (evict_invalid_stakes_cache_entries::id(), "evict invalid stakes cache entries on epoch boundaries"), (spl_associated_token_account_v1_0_4::id(), "SPL Associated Token Account Program release version 1.0.4, tied to token 3.3.0 #22648"), (bank_tranaction_count_fix::id(), "Fixes Bank::transaction_count to include all committed transactions, not just successful ones"), + (update_syscall_base_costs::id(), "Update syscall base costs"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter() diff --git a/sdk/src/process_instruction.rs b/sdk/src/process_instruction.rs index 2c26a7a94c..78aebdad8c 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -185,6 +185,8 @@ pub struct BpfComputeBudget { /// Number of compute units per additional 32k heap above the default (~.5 /// us per 32k at 15 units/us rounded up) pub heap_cost: u64, + /// Memory operation syscall base cost + pub mem_op_base_cost: u64, } impl Default for BpfComputeBudget { @@ -213,6 +215,7 @@ impl BpfComputeBudget { secp256k1_recover_cost: 25_000, heap_size: None, heap_cost: 8, + mem_op_base_cost: 10, } } }