diff --git a/Cargo.lock b/Cargo.lock index 8382a95768..15ca24a933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -606,7 +606,7 @@ dependencies = [ "anyhow", "casper-sdk", "casper-sdk-sys", - "clap 4.5.20", + "clap 4.5.21", "clap-cargo", "libloading", "serde_json", @@ -741,6 +741,7 @@ dependencies = [ "casper-wasm", "casper-wasm-utils", "casper-wasmi", + "clap 4.5.21", "criterion 0.3.6", "datasize", "either", @@ -768,9 +769,11 @@ dependencies = [ "strum 0.24.1", "tempfile", "thiserror", + "toml 0.8.19", "tracing", "uint", "walrus", + "wat", ] [[package]] @@ -983,7 +986,7 @@ dependencies = [ "casper-executor-wasm-common", "casper-sdk-sys", "cfg-if 1.0.0", - "clap 4.5.20", + "clap 4.5.21", "const-fnv1a-hash", "impl-trait-for-tuples", "linkme", @@ -1099,7 +1102,7 @@ dependencies = [ name = "casper-updater" version = "0.3.0" dependencies = [ - "clap 4.5.20", + "clap 4.5.21", "once_cell", "regex", "semver", @@ -1249,7 +1252,7 @@ dependencies = [ "bitflags 1.3.2", "strsim 0.8.0", "textwrap 0.11.0", - "unicode-width", + "unicode-width 0.1.10", "vec_map", ] @@ -1272,9 +1275,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive 4.5.18", @@ -1288,14 +1291,14 @@ checksum = "23b2ea69cefa96b848b73ad516ad1d59a195cdf9263087d977f648a818c8b43e" dependencies = [ "anstyle", "cargo_metadata", - "clap 4.5.20", + "clap 4.5.21", ] [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -1604,7 +1607,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.20", + "clap 4.5.21", "criterion-plot 0.5.0", "is-terminal", "itertools 0.10.5", @@ -6512,7 +6515,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width", + "unicode-width 0.1.10", ] [[package]] @@ -7168,6 +7171,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -7576,12 +7585,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.219.1" +version = "0.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54" +checksum = "ebf48234b389415b226a4daef6562933d38c7b28a8b8f64c5c4130dad1561ab7" dependencies = [ "leb128", - "wasmparser 0.219.1", + "wasmparser 0.220.0", ] [[package]] @@ -7771,6 +7780,16 @@ dependencies = [ "indexmap 2.6.0", ] +[[package]] +name = "wasmparser" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e246c2772ce3ebc83f89a2d4487ac5794cad6c309b2071818a88c7db7c36d87b" +dependencies = [ + "bitflags 2.6.0", + "indexmap 2.6.0", +] + [[package]] name = "wasmprinter" version = "0.219.1" @@ -7784,22 +7803,22 @@ dependencies = [ [[package]] name = "wast" -version = "219.0.1" +version = "220.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f79a9d9df79986a68689a6b40bcc8d5d40d807487b235bebc2ac69a242b54a1" +checksum = "4e708c8de08751fd66e70961a32bae9d71901f14a70871e181cb8461a3bb3165" dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width", - "wasm-encoder 0.219.1", + "unicode-width 0.2.0", + "wasm-encoder 0.220.0", ] [[package]] name = "wat" -version = "1.219.1" +version = "1.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc3cf014fb336883a411cd662f987abf6a1d2a27f2f0008616a0070bbf6bd0d" +checksum = "de4f1d7d59614ba690541360102b995c4eb1b9ed373701d5102cc1a968b1c5a3" dependencies = [ "wast", ] diff --git a/execution_engine/Cargo.toml b/execution_engine/Cargo.toml index 6b303a6953..9cdc3b50d6 100644 --- a/execution_engine/Cargo.toml +++ b/execution_engine/Cargo.toml @@ -49,6 +49,9 @@ tempfile = "3.4.0" thiserror = "1.0.18" tracing = "0.1.18" uint = "0.9.0" +clap = { version = "4.5.21", features = ["derive"] } +toml = "0.8.19" +wat = "1.220.0" [dev-dependencies] assert_matches = "1.3.0" diff --git a/execution_engine/src/bin/run_wasm.rs b/execution_engine/src/bin/run_wasm.rs new file mode 100644 index 0000000000..0747f1b2de --- /dev/null +++ b/execution_engine/src/bin/run_wasm.rs @@ -0,0 +1,237 @@ +use std::{ + fs, + path::{Path, PathBuf}, + time::{Duration, Instant}, +}; + +use casper_types::WasmConfig; + +use casper_execution_engine::runtime; +use casper_wasmi::{ + memory_units::Pages, Externals, FuncInstance, HostError, ImportsBuilder, MemoryInstance, + ModuleImportResolver, ModuleInstance, RuntimeValue, Signature, +}; + +fn prepare_instance(module_bytes: &[u8], chainspec: &ChainspecConfig) -> casper_wasmi::ModuleRef { + let wasm_module = runtime::preprocess(chainspec.wasm_config, module_bytes).unwrap(); + let module = casper_wasmi::Module::from_casper_wasm_module(wasm_module).unwrap(); + let resolver = MinimalWasmiResolver::default(); + let mut imports = ImportsBuilder::new(); + imports.push_resolver("env", &resolver); + let not_started_module = ModuleInstance::new(&module, &imports).unwrap(); + + assert!(!not_started_module.has_start()); + + let instance = not_started_module.not_started_instance(); + instance.clone() +} + +struct RunWasmInfo { + elapsed: Duration, + gas_used: u64, +} + +fn run_wasm( + module_bytes: Vec, + chainspec: &ChainspecConfig, + func_name: &str, + args: &[String], +) -> ( + Result, casper_wasmi::Error>, + RunWasmInfo, +) { + println!("Invoke export {:?} with args {:?}", func_name, args); + + let instance = prepare_instance(&module_bytes, chainspec); + + let params = { + let export = instance.export_by_name(func_name).unwrap(); + let func = export.as_func().unwrap(); + func.signature().params().to_owned() + }; + + let args = { + assert_eq!(args.len(), params.len(), "Not enough arguments supplied"); + let mut vec = Vec::new(); + for (input_arg, func_arg) in args.iter().zip(params.into_iter()) { + let value = match func_arg { + casper_wasmi::ValueType::I32 => { + casper_wasmi::RuntimeValue::I32(input_arg.parse().unwrap()) + } + casper_wasmi::ValueType::I64 => { + casper_wasmi::RuntimeValue::I64(input_arg.parse().unwrap()) + } + casper_wasmi::ValueType::F32 => todo!(), + casper_wasmi::ValueType::F64 => todo!(), + }; + vec.push(value); + } + vec + }; + + let start = Instant::now(); + + let mut externals = MinimalWasmiExternals::new(0, chainspec.transaction_config.block_gas_limit); + let result: Result, casper_wasmi::Error> = + instance + .clone() + .invoke_export(func_name, &args, &mut externals); + + let info = RunWasmInfo { + elapsed: start.elapsed(), + gas_used: externals.gas_used, + }; + + (result, info) +} +use clap::Parser; +use serde::Deserialize; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + #[arg(value_name = "MODULE")] + wasm_file: PathBuf, + #[arg(long = "invoke", value_name = "FUNCTION")] + invoke: Option, + /// Arguments given to the Wasm module or the invoked function. + #[arg(value_name = "ARGS")] + args: Vec, + #[arg(short, long)] + chainspec_file: Option, +} + +fn load_wasm_file>(path: P) -> Vec { + let path = path.as_ref(); + let bytes = fs::read(path).expect("valid file"); + match path.extension() { + Some(ext) if ext.to_ascii_lowercase() == "wat" => { + wat::parse_bytes(&bytes).expect("valid wat").into_owned() + } + None | Some(_) => bytes, + } +} + +#[derive(Deserialize, Clone, Default, Debug)] +struct TransactionConfig { + block_gas_limit: u64, +} + +/// in the chainspec file, it can continue to be parsed as an `ChainspecConfig`. +#[derive(Deserialize, Clone, Default, Debug)] +struct ChainspecConfig { + /// WasmConfig. + #[serde(rename = "wasm")] + pub wasm_config: WasmConfig, + #[serde(rename = "transactions")] + pub transaction_config: TransactionConfig, +} + +fn main() { + let args = Args::parse(); + + let chainspec_file = args.chainspec_file.expect("chainspec file"); + println!("Using chainspec file {:?}", chainspec_file.display()); + let chainspec_data = fs::read_to_string(chainspec_file.as_path()).expect("valid file"); + let chainspec_config: ChainspecConfig = + toml::from_str(&chainspec_data).expect("valid chainspec"); + + let wasm_bytes = load_wasm_file(args.wasm_file); + + if let Some(func_name) = args.invoke { + let (result, info) = run_wasm(wasm_bytes, &chainspec_config, &func_name, &args.args); + + println!("result: {:?}", result); + println!("elapsed: {:?}", info.elapsed); + println!("gas used: {}", info.gas_used); + } +} + +#[derive(Default)] +struct MinimalWasmiResolver(()); + +#[derive(Debug)] +struct MinimalWasmiExternals { + gas_used: u64, + block_gas_limit: u64, +} + +impl MinimalWasmiExternals { + fn new(gas_used: u64, block_gas_limit: u64) -> Self { + Self { + gas_used, + block_gas_limit, + } + } +} + +const GAS_FUNC_IDX: usize = 0; + +impl ModuleImportResolver for MinimalWasmiResolver { + fn resolve_func( + &self, + field_name: &str, + _signature: &casper_wasmi::Signature, + ) -> Result { + if field_name == "gas" { + Ok(FuncInstance::alloc_host( + Signature::new(&[casper_wasmi::ValueType::I32; 1][..], None), + GAS_FUNC_IDX, + )) + } else { + Err(casper_wasmi::Error::Instantiation(format!( + "Export {} not found", + field_name + ))) + } + } + + fn resolve_memory( + &self, + field_name: &str, + memory_type: &casper_wasmi::MemoryDescriptor, + ) -> Result { + if field_name == "memory" { + Ok(MemoryInstance::alloc( + Pages(memory_type.initial() as usize), + memory_type.maximum().map(|x| Pages(x as usize)), + )?) + } else { + panic!("invalid exported memory name {}", field_name); + } + } +} + +#[derive(thiserror::Error, Debug)] +#[error("gas limit")] +struct GasLimit; + +impl HostError for GasLimit {} + +impl Externals for MinimalWasmiExternals { + fn invoke_index( + &mut self, + index: usize, + args: casper_wasmi::RuntimeArgs, + ) -> Result, casper_wasmi::Trap> { + if index == GAS_FUNC_IDX { + let gas_used: u32 = args.nth_checked(0)?; + // match gas_used.checked_add( + match self.gas_used.checked_add(gas_used.into()) { + Some(new_gas_used) if new_gas_used > self.block_gas_limit => { + return Err(GasLimit.into()); + } + Some(new_gas_used) => { + // dbg!(&new_gas_used, &self.block_gas_limit); + self.gas_used = new_gas_used; + } + None => { + unreachable!(); + } + } + Ok(None) + } else { + unreachable!(); + } + } +} diff --git a/execution_engine/src/runtime/mod.rs b/execution_engine/src/runtime/mod.rs index 8c4536d5f7..2b20ca6ba8 100644 --- a/execution_engine/src/runtime/mod.rs +++ b/execution_engine/src/runtime/mod.rs @@ -8,7 +8,7 @@ mod host_function_flag; mod mint_internal; pub mod stack; mod utils; -mod wasm_prep; +pub(crate) mod wasm_prep; use std::{ cmp, @@ -71,8 +71,9 @@ use crate::{ }; pub use stack::{RuntimeStack, RuntimeStackFrame, RuntimeStackOverflow}; pub use wasm_prep::{ - PreprocessingError, WasmValidationError, DEFAULT_BR_TABLE_MAX_SIZE, DEFAULT_MAX_GLOBALS, - DEFAULT_MAX_PARAMETER_COUNT, DEFAULT_MAX_TABLE_SIZE, + cycles_for_instruction, preprocess, PreprocessingError, WasmValidationError, + DEFAULT_BR_TABLE_MAX_SIZE, DEFAULT_MAX_GLOBALS, DEFAULT_MAX_PARAMETER_COUNT, + DEFAULT_MAX_TABLE_SIZE, }; #[derive(Debug)] @@ -1322,7 +1323,7 @@ where let wasm_config = engine_config.wasm_config(); #[cfg(feature = "test-support")] let max_stack_height = wasm_config.v1().max_stack_height(); - let module = wasm_prep::preprocess(*wasm_config, module_bytes)?; + let module = preprocess(*wasm_config, module_bytes)?; let (instance, memory) = utils::instance_and_memory(module.clone(), protocol_version, engine_config)?; self.memory = Some(memory); diff --git a/execution_engine/src/runtime/wasm_prep.rs b/execution_engine/src/runtime/wasm_prep.rs index 220d5643e8..773e6a88e8 100644 --- a/execution_engine/src/runtime/wasm_prep.rs +++ b/execution_engine/src/runtime/wasm_prep.rs @@ -5,7 +5,8 @@ use thiserror::Error; use casper_types::{OpcodeCosts, WasmConfig}; use casper_wasm::elements::{ - self, External, Instruction, Internal, MemorySection, Module, Section, TableType, Type, + self, External, Instruction, Internal, MemorySection, Module, Section, SignExtInstruction, + TableType, Type, }; use casper_wasm_utils::{ self, @@ -382,7 +383,7 @@ fn ensure_valid_imports(module: &Module) -> Result<(), WasmValidationError> { /// /// In case the preprocessing rules can't be applied, an error is returned. /// Otherwise, this method returns a valid module ready to be executed safely on the host. -pub(crate) fn preprocess( +pub fn preprocess( wasm_config: WasmConfig, module_bytes: &[u8], ) -> Result { @@ -475,11 +476,235 @@ pub fn get_module_from_entry_points( } } +/// Returns the cost of executing a single instruction. +/// +/// This is benchmarked on a reference hardware, and calculated based on the multiplies of the +/// cheapest opcode (nop) in the given instruction. +/// +/// For instance, nop will always have cycle cost of 1, and all other opcodes will have a multiple +/// of that. +/// +/// The number of cycles for each instruction correlates, but not directly, to the reference x86_64 +/// CPU cycles it takes to execute the instruction as the interpreter does extra work to invoke an +/// instruction. +pub fn cycles_for_instruction(instruction: &Instruction) -> u32 { + match instruction { + // The following instructions signal the beginning of a block, loop, or if construct. They + // don't have any static cost. Validated in benchmarks. + Instruction::Loop(_) => 1, + Instruction::Block(_) => 1, + Instruction::Else => 1, + Instruction::End => 1, + + Instruction::Unreachable => 1, + Instruction::Nop => 1, + + Instruction::If(_) => 3, + + // These instructions are resuming execution from previously saved location (produced by + // loop or block). + Instruction::Br(_) => 1, + Instruction::BrIf(_) => 3, + Instruction::BrTable(_) => 5, + + Instruction::Return => 1, + + // Call opcodes are charged for each of the opcode individually. Validated in benchmarks. + Instruction::Call(_) => 22, + Instruction::CallIndirect(_, _) => 27, + + Instruction::Drop => 1, + + // Select opcode is validated in benchmarks. + Instruction::Select => 11, + + Instruction::GetLocal(_) | Instruction::SetLocal(_) | Instruction::TeeLocal(_) => 5, + + Instruction::GetGlobal(_) => 7, + Instruction::SetGlobal(_) => 5, + + Instruction::I64Load32S(_, _) + | Instruction::F32Load(_, _) + | Instruction::F64Load(_, _) + | Instruction::I32Load(_, _) + | Instruction::I64Load(_, _) + | Instruction::I32Load8S(_, _) + | Instruction::I64Load32U(_, _) + | Instruction::I64Load8U(_, _) + | Instruction::I64Load8S(_, _) + | Instruction::I32Load8U(_, _) + | Instruction::I64Load16U(_, _) + | Instruction::I32Load16U(_, _) + | Instruction::I64Load16S(_, _) + | Instruction::I32Load16S(_, _) => 8, + + Instruction::I32Store(_, _) + | Instruction::I64Store(_, _) + | Instruction::F32Store(_, _) + | Instruction::F64Store(_, _) + | Instruction::I32Store8(_, _) + | Instruction::I32Store16(_, _) + | Instruction::I64Store8(_, _) + | Instruction::I64Store16(_, _) + | Instruction::I64Store32(_, _) => 4, + + Instruction::CurrentMemory(_) => 5, + Instruction::GrowMemory(_) => 5, + + Instruction::I32Const(_) + | Instruction::I64Const(_) + | Instruction::F32Const(_) + | Instruction::F64Const(_) => 5, + + Instruction::I32Eqz + | Instruction::I32Eq + | Instruction::I32Ne + | Instruction::I32LtS + | Instruction::I32LtU + | Instruction::I32GtS + | Instruction::I32GtU + | Instruction::I32LeS + | Instruction::I32LeU + | Instruction::I32GeS + | Instruction::I32GeU + | Instruction::I64Eqz + | Instruction::I64Eq + | Instruction::I64Ne + | Instruction::I64LtS + | Instruction::I64LtU + | Instruction::I64GtS + | Instruction::I64GtU + | Instruction::I64LeS + | Instruction::I64LeU + | Instruction::I64GeS + | Instruction::I64GeU => 5, + + Instruction::F32Eq + | Instruction::F32Ne + | Instruction::F32Lt + | Instruction::F32Gt + | Instruction::F32Le + | Instruction::F32Ge + | Instruction::F64Eq + | Instruction::F64Ne + | Instruction::F64Lt + | Instruction::F64Gt + | Instruction::F64Le + | Instruction::F64Ge => 5, + + Instruction::I32Clz | Instruction::I32Ctz | Instruction::I32Popcnt => 5, + + Instruction::I32Add | Instruction::I32Sub => 5, + + Instruction::I32Mul => 5, + + Instruction::I32DivS + | Instruction::I32DivU + | Instruction::I32RemS + | Instruction::I32RemU => 5, + + Instruction::I32And + | Instruction::I32Or + | Instruction::I32Xor + | Instruction::I32Shl + | Instruction::I32ShrS + | Instruction::I32ShrU + | Instruction::I32Rotl + | Instruction::I32Rotr + | Instruction::I64Clz + | Instruction::I64Ctz + | Instruction::I64Popcnt => 5, + + Instruction::I64Add | Instruction::I64Sub => 5, + Instruction::I64Mul => 5, + + Instruction::I64DivS + | Instruction::I64DivU + | Instruction::I64RemS + | Instruction::I64RemU => 5, + + Instruction::I64And + | Instruction::I64Or + | Instruction::I64Xor + | Instruction::I64Shl + | Instruction::I64ShrS + | Instruction::I64ShrU + | Instruction::I64Rotl + | Instruction::I64Rotr => 5, + + Instruction::F32Abs + | Instruction::F32Neg + | Instruction::F32Ceil + | Instruction::F32Floor + | Instruction::F32Trunc + | Instruction::F32Nearest + | Instruction::F32Sqrt + | Instruction::F32Add + | Instruction::F32Sub + | Instruction::F32Mul + | Instruction::F32Div + | Instruction::F32Min + | Instruction::F32Max + | Instruction::F32Copysign + | Instruction::F64Abs + | Instruction::F64Neg + | Instruction::F64Ceil + | Instruction::F64Floor + | Instruction::F64Trunc + | Instruction::F64Nearest + | Instruction::F64Sqrt + | Instruction::F64Add + | Instruction::F64Sub + | Instruction::F64Mul + | Instruction::F64Div + | Instruction::F64Min + | Instruction::F64Max + | Instruction::F64Copysign => 5, + + Instruction::I32WrapI64 | Instruction::I64ExtendSI32 | Instruction::I64ExtendUI32 => 5, + + Instruction::F32ConvertSI32 + | Instruction::F32ConvertUI32 + | Instruction::F32ConvertSI64 + | Instruction::F32ConvertUI64 + | Instruction::F32DemoteF64 + | Instruction::F64ConvertSI32 + | Instruction::F64ConvertUI32 + | Instruction::F64ConvertSI64 + | Instruction::F64ConvertUI64 + | Instruction::F64PromoteF32 => 5, + + // Unsupported reinterpretation operators for floats. + Instruction::I32ReinterpretF32 + | Instruction::I64ReinterpretF64 + | Instruction::F32ReinterpretI32 + | Instruction::F64ReinterpretI64 => 5, + + Instruction::SignExt(SignExtInstruction::I32Extend8S) + | Instruction::SignExt(SignExtInstruction::I32Extend16S) + | Instruction::SignExt(SignExtInstruction::I64Extend8S) + | Instruction::SignExt(SignExtInstruction::I64Extend16S) + | Instruction::SignExt(SignExtInstruction::I64Extend32S) => 5, + + Instruction::I32TruncUF32 | Instruction::I64TruncSF32 => 40, + + Instruction::I32TruncSF32 | Instruction::I64TruncUF32 => 42, + + Instruction::I32TruncSF64 + | Instruction::I32TruncUF64 + | Instruction::I64TruncUF64 + | Instruction::I64TruncSF64 => 195, + } +} + struct RuledOpcodeCosts(OpcodeCosts); -impl Rules for RuledOpcodeCosts { - fn instruction_cost(&self, instruction: &Instruction) -> Option { +impl RuledOpcodeCosts { + /// Returns the cost multiplier of executing a single instruction. + fn instruction_cost_multiplier(&self, instruction: &Instruction) -> Option { let costs = self.0; + + // Obtain the gas cost multiplier for the instruction. match instruction { Instruction::Unreachable => Some(costs.unreachable), Instruction::Nop => Some(costs.nop), @@ -686,6 +911,19 @@ impl Rules for RuledOpcodeCosts { Instruction::SignExt(_) => Some(costs.sign), } } +} + +impl Rules for RuledOpcodeCosts { + fn instruction_cost(&self, instruction: &Instruction) -> Option { + // The number of cycles for each instruction correlates, but not directly, to the reference + // x86_64 CPU cycles. + let cycles = cycles_for_instruction(instruction); + + // The cost of executing an instruction is the number of cycles times the cost of a nop. + let multiplier = self.instruction_cost_multiplier(instruction)?; + + cycles.checked_mul(multiplier) + } fn memory_grow_cost(&self) -> Option { NonZeroU32::new(self.0.grow_memory).map(MemoryGrowCost::Linear) diff --git a/execution_engine_testing/test_support/src/execute_request_builder.rs b/execution_engine_testing/test_support/src/execute_request_builder.rs index 2743a48ddb..f9d393aa72 100644 --- a/execution_engine_testing/test_support/src/execute_request_builder.rs +++ b/execution_engine_testing/test_support/src/execute_request_builder.rs @@ -50,6 +50,8 @@ pub struct ExecuteRequestBuilder { authorization_keys: BTreeSet, } +const DEFAULT_GAS_LIMIT: u64 = 5_000_u64 * 10u64.pow(9); + impl ExecuteRequestBuilder { /// The default value used for `WasmV1Request::state_hash`. pub const DEFAULT_STATE_HASH: Digest = Digest::from_raw([1; 32]); @@ -68,12 +70,9 @@ impl ExecuteRequestBuilder { 0, ); let authorization_keys = session_input_data.signers(); - let session = WasmV1Request::new_session( - block_info, - Gas::new(5_000_000_000_000_u64), - session_input_data, - ) - .unwrap(); + let session = + WasmV1Request::new_session(block_info, Gas::new(DEFAULT_GAS_LIMIT), session_input_data) + .unwrap(); let payment: Option; let payment_gas_limit: Gas; @@ -93,7 +92,7 @@ impl ExecuteRequestBuilder { ); let request = WasmV1Request::new_custom_payment( block_info, - Gas::new(5_000_000_000_000_u64), + Gas::new(DEFAULT_GAS_LIMIT), session_input_data, ) .unwrap(); @@ -132,7 +131,7 @@ impl ExecuteRequestBuilder { 0, ); let session = deploy_item - .new_session_from_deploy_item(block_info, Gas::new(5_000_000_000_000_u64)) + .new_session_from_deploy_item(block_info, Gas::new(DEFAULT_GAS_LIMIT)) .unwrap(); let payment: Option; @@ -152,7 +151,7 @@ impl ExecuteRequestBuilder { 0, ); let request = deploy_item - .new_custom_payment_from_deploy_item(block_info, Gas::new(5_000_000_000_000_u64)) + .new_custom_payment_from_deploy_item(block_info, Gas::new(DEFAULT_GAS_LIMIT)) .unwrap(); payment = Some(request.executable_item); payment_gas_limit = request.gas_limit; diff --git a/execution_engine_testing/tests/src/test/explorer/faucet.rs b/execution_engine_testing/tests/src/test/explorer/faucet.rs index 6a2e8b36b4..fd3cba66f2 100644 --- a/execution_engine_testing/tests/src/test/explorer/faucet.rs +++ b/execution_engine_testing/tests/src/test/explorer/faucet.rs @@ -663,11 +663,13 @@ fn faucet_costs() { // This test will fail if execution costs vary. The expected costs should not be updated // without understanding why the cost has changed. If the costs do change, it should be // reflected in the "Costs by Entry Point" section of the faucet crate's README.md. - const EXPECTED_FAUCET_INSTALL_COST: u64 = 146_744_539_794; + const EXPECTED_FAUCET_INSTALL_COST: u64 = 144_782_774_054; - const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 144_208_890; - const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_706_199_403; - const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_645_013_716; + const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 70_836_755; + + const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_645_108_193; + + const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_545_778_741; let installer_account = AccountHash::new([1u8; 32]); let user_account: AccountHash = AccountHash::new([2u8; 32]); diff --git a/execution_engine_testing/tests/src/test/gas_counter.rs b/execution_engine_testing/tests/src/test/gas_counter.rs deleted file mode 100644 index e4c694bffc..0000000000 --- a/execution_engine_testing/tests/src/test/gas_counter.rs +++ /dev/null @@ -1,179 +0,0 @@ -use assert_matches::assert_matches; -use casper_wasm::{ - builder, - elements::{BlockType, Instruction, Instructions}, -}; - -use casper_engine_test_support::{ - DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, ARG_AMOUNT, - DEFAULT_ACCOUNT_ADDR, DEFAULT_PAYMENT, LOCAL_GENESIS_REQUEST, -}; -use casper_execution_engine::{engine_state::Error, runtime::PreprocessingError}; -use casper_types::{ - addressable_entity::DEFAULT_ENTRY_POINT_NAME, runtime_args, Gas, OpcodeCosts, RuntimeArgs, -}; - -use crate::test::regression::test_utils::make_gas_counter_overflow; - -/// Creates session code with opcodes -fn make_session_code_with(instructions: Vec) -> Vec { - let module = builder::module() - .function() - // A signature with 0 params and no return type - .signature() - .build() - .body() - // Generated instructions for our entrypoint - .with_instructions(Instructions::new(instructions)) - .build() - .build() - // Export above function - .export() - .field(DEFAULT_ENTRY_POINT_NAME) - .build() - // Memory section is mandatory - .memory() - .build() - .build(); - casper_wasm::serialize(module).expect("should serialize") -} - -#[ignore] -#[test] -fn should_fail_to_overflow_gas_counter() { - let mut builder = LmdbWasmTestBuilder::default(); - - let session_bytes = make_gas_counter_overflow(); - - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(session_bytes, RuntimeArgs::default()) - .with_standard_payment(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - - builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - - builder.exec(exec_request).commit(); - - let exec_result = builder - .get_exec_result_owned(0) - .expect("should have response"); - let lhs = exec_result.error().expect("should have error"); - assert_matches!( - lhs, - Error::WasmPreprocessing(PreprocessingError::OperationForbiddenByGasRules) - ); -} - -#[ignore] -#[test] -fn should_correctly_measure_gas_for_opcodes() { - let opcode_costs = OpcodeCosts::default(); - - const GROW_PAGES: u32 = 1; - - // A vector of expected cost of given WASM instruction. - // First element of the tuple represents and option where Some case represents metered - // instruction and None an instruction that's not accounted for. - // - // The idea here is to execute hand written WASM and compare the execution result's gas counter - // with the expected gathered from here. - let opcodes = vec![ - (Some(opcode_costs.nop), Instruction::Nop), - ( - Some(opcode_costs.current_memory), - Instruction::CurrentMemory(0), - ), // Push size to stack - (Some(opcode_costs.op_const), Instruction::I32Const(10)), - (Some(opcode_costs.mul), Instruction::I32Mul), // memory.size * 10 - (Some(opcode_costs.op_const), Instruction::I32Const(11)), - (Some(opcode_costs.add), Instruction::I32Add), - (Some(opcode_costs.op_const), Instruction::I32Const(12)), - (Some(opcode_costs.add), Instruction::I32Sub), - (Some(opcode_costs.op_const), Instruction::I32Const(13)), - (Some(opcode_costs.div), Instruction::I32DivU), - (Some(opcode_costs.op_const), Instruction::I32Const(3)), - (Some(opcode_costs.bit), Instruction::I32Shl), // x<<3 == x*(2*3) - // Store computation - (Some(opcode_costs.op_const), Instruction::I32Const(0)), // offset - (Some(opcode_costs.store), Instruction::I32Store(0, 4)), /* Store `memory.size * 10` on - * the heap */ - // Grow by N pages - ( - Some(opcode_costs.op_const), - Instruction::I32Const(GROW_PAGES as i32), - ), - // memory.grow is metered by the number of pages - ( - Some(opcode_costs.grow_memory * (GROW_PAGES + 1)), - Instruction::GrowMemory(0), - ), - (Some(opcode_costs.op_const), Instruction::I32Const(0)), - (Some(opcode_costs.store), Instruction::I32Store(0, 4)), /* Store `grow_memory` result - * whatever it is */ - // if 0 { nop } else { nop; nop; } - (Some(opcode_costs.op_const), Instruction::I32Const(0)), - ( - Some(opcode_costs.control_flow.op_if), - Instruction::If(BlockType::NoResult), - ), - (None, Instruction::Nop), - (None, Instruction::Else), - // else clause is accounted for only - (Some(opcode_costs.nop), Instruction::Nop), - (Some(opcode_costs.nop), Instruction::Nop), - (None, Instruction::End), - // 0 == 1 - (Some(opcode_costs.op_const), Instruction::I32Const(0)), - (Some(opcode_costs.op_const), Instruction::I32Const(1)), - (Some(opcode_costs.integer_comparison), Instruction::I32Eqz), - (Some(opcode_costs.store), Instruction::I32Store(0, 4)), /* Store `eqz` result - * whatever it is */ - // i32 -> i64 - (Some(opcode_costs.op_const), Instruction::I32Const(123)), - (Some(opcode_costs.conversion), Instruction::I64ExtendSI32), - (Some(opcode_costs.control_flow.drop), Instruction::Drop), /* Discard the result */ - // Sentinel instruction that's required to be present but it's not accounted for - (None, Instruction::End), - ]; - - let instructions = opcodes.iter().map(|(_, instr)| instr.clone()).collect(); - let accounted_opcodes: Vec<_> = opcodes.iter().filter_map(|(cost, _)| *cost).collect(); - - let session_bytes = make_session_code_with(instructions); - - let mut builder = LmdbWasmTestBuilder::default(); - - builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - - let deploy_item = DeployItemBuilder::new() - .with_address(*DEFAULT_ACCOUNT_ADDR) - .with_session_bytes(session_bytes, RuntimeArgs::default()) - .with_standard_payment(runtime_args! { - ARG_AMOUNT => *DEFAULT_PAYMENT - }) - .with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR]) - .with_deploy_hash([42; 32]) - .build(); - let exec_request = ExecuteRequestBuilder::from_deploy_item(&deploy_item).build(); - - builder.exec(exec_request).commit().expect_success(); - - let gas_cost = builder.last_exec_gas_consumed(); - let expected_cost = accounted_opcodes - .clone() - .into_iter() - .map(Gas::from) - .try_fold(Gas::default(), |acc, cost| acc.checked_add(cost)) - .expect("should add gas costs"); - assert_eq!( - gas_cost, expected_cost, - "accounted costs {:?}", - accounted_opcodes - ); -} diff --git a/execution_engine_testing/tests/src/test/mod.rs b/execution_engine_testing/tests/src/test/mod.rs index 37fe904390..273d2e39b5 100644 --- a/execution_engine_testing/tests/src/test/mod.rs +++ b/execution_engine_testing/tests/src/test/mod.rs @@ -6,7 +6,6 @@ mod contract_messages; mod counter_factory; mod deploy; mod explorer; -mod gas_counter; mod get_balance; mod groups; mod host_function_costs; diff --git a/execution_engine_testing/tests/src/test/regression/slow_input.rs b/execution_engine_testing/tests/src/test/regression/slow_input.rs index e21d96ff2a..8eaf42b200 100644 --- a/execution_engine_testing/tests/src/test/regression/slow_input.rs +++ b/execution_engine_testing/tests/src/test/regression/slow_input.rs @@ -3,7 +3,6 @@ use std::mem; use casper_engine_test_support::{ ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; -use casper_execution_engine::{engine_state::Error, execution::ExecError}; use casper_types::{ addressable_entity::DEFAULT_ENTRY_POINT_NAME, Gas, RuntimeArgs, DEFAULT_CONTROL_FLOW_BR_TABLE_MULTIPLIER, @@ -11,124 +10,6 @@ use casper_types::{ use walrus::{ir::BinaryOp, FunctionBuilder, InstrSeqBuilder, Module, ModuleConfig, ValType}; -const SLOW_INPUT: &str = r#"(module - (type $CASPER_RET_TY (func (param i32 i32))) - (type $CALL_TY (func)) - (type $BUSY_LOOP_TY (func (param i32 i32 i32) (result i32))) - (import "env" "casper_ret" (func $CASPER_RET (type $CASPER_RET_TY))) - (func $CALL_FN (type $CALL_TY) - (local i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) - local.get 0 - i64.const -2259106222686656124 - local.get 0 - i32.const 16 - i32.add - i32.const 18 - i32.const 50000 - call $BUSY_LOOP_FN - drop - local.get 0 - i32.const 12 - i32.add - i32.const 770900 - call $CASPER_RET - unreachable) - (func $BUSY_LOOP_FN (type $BUSY_LOOP_TY) (param i32 i32 i32) (result i32) - (local i32) - loop $OUTER_LOOP ;; label = @1 - i32.const 0 - i32.eqz - br_if $OUTER_LOOP (;@1;) - local.get 0 - local.set 3 - loop $INNER_LOOP ;; label = @2 - local.get 3 - local.get 1 - i32.store8 - local.get 3 - local.set 3 - local.get 2 - i32.const -1 - i32.add - local.tee 2 - br_if $INNER_LOOP (;@2;) - end - end - local.get 0) - (memory $MEMORY 11) - (export "memory" (memory $MEMORY)) - (export "call" (func $CALL_FN)))"#; - -#[ignore] -#[test] -fn should_measure_slow_input() { - let module_bytes = wat::parse_str(SLOW_INPUT).unwrap(); - let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = ExecuteRequestBuilder::module_bytes( - *DEFAULT_ACCOUNT_ADDR, - module_bytes, - RuntimeArgs::default(), - ) - .build(); - builder.exec(exec_request).commit(); - let error = builder.get_error().expect("must have an error"); - assert!(matches!(error, Error::Exec(ExecError::GasLimit))); -} - -#[ignore] -#[test] -fn should_measure_slow_input_with_infinite_br_loop() { - let module_bytes = make_cpu_burner_br(); - - let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = ExecuteRequestBuilder::module_bytes( - *DEFAULT_ACCOUNT_ADDR, - module_bytes, - RuntimeArgs::default(), - ) - .build(); - builder.exec(exec_request).commit(); - let error = builder.get_error().expect("must have an error"); - assert!(matches!(error, Error::Exec(ExecError::GasLimit))); -} - -#[ignore] -#[test] -fn should_measure_br_if_cpu_burner_with_br_if_iterations() { - let module_bytes = cpu_burner_br_if(u32::MAX as i64); - let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = ExecuteRequestBuilder::module_bytes( - *DEFAULT_ACCOUNT_ADDR, - module_bytes, - RuntimeArgs::default(), - ) - .build(); - builder.exec(exec_request).commit(); - let error = builder.get_error().expect("must have an error"); - assert!(matches!(error, Error::Exec(ExecError::GasLimit))); -} - -#[ignore] -#[test] -fn should_measure_br_table_cpu_burner_with_br_table_iterations() { - let module_bytes = cpu_burner_br_table(u32::MAX as i64); - - let mut builder = LmdbWasmTestBuilder::default(); - builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); - let exec_request = ExecuteRequestBuilder::module_bytes( - *DEFAULT_ACCOUNT_ADDR, - module_bytes, - RuntimeArgs::default(), - ) - .build(); - builder.exec(exec_request).commit(); - let error = builder.get_error().expect("must have an error"); - assert!(matches!(error, Error::Exec(ExecError::GasLimit))); -} - #[ignore] #[test] fn should_charge_extra_per_amount_of_br_table_elements() { @@ -171,32 +52,18 @@ fn should_charge_extra_per_amount_of_br_table_elements() { "larger br_table should cost more gas" ); + let br_table_cycles = 5; + assert_eq!( gas_cost_2.checked_sub(gas_cost_1), Some(Gas::from( - (M_ELEMENTS - N_ELEMENTS) * DEFAULT_CONTROL_FLOW_BR_TABLE_MULTIPLIER + (M_ELEMENTS - N_ELEMENTS) * DEFAULT_CONTROL_FLOW_BR_TABLE_MULTIPLIER * br_table_cycles )), "the cost difference should equal to exactly the size of br_table difference " ); } -fn make_cpu_burner_br() -> Vec { - let mut module = Module::with_config(ModuleConfig::new()); - - let _memory_id = module.memories.add_local(false, 11, None); - - let mut call_func = FunctionBuilder::new(&mut module.types, &[], &[]); - - call_func.func_body().loop_(None, |loop_| { - loop_.br(loop_.id()); - }); - - let call = call_func.finish(Vec::new(), &mut module.funcs); - module.exports.add(DEFAULT_ENTRY_POINT_NAME, call); - - module.emit_wasm() -} - +#[allow(dead_code)] fn cpu_burner_br_if(iterations: i64) -> Vec { let mut module = Module::with_config(ModuleConfig::new()); @@ -240,6 +107,7 @@ fn cpu_burner_br_if(iterations: i64) -> Vec { module.emit_wasm() } +#[allow(dead_code)] fn cpu_burner_br_table(iterations: i64) -> Vec { let mut module = Module::with_config(ModuleConfig::new()); diff --git a/resources/local/chainspec.toml.in b/resources/local/chainspec.toml.in index ce2cedf4ec..3ed8212201 100644 --- a/resources/local/chainspec.toml.in +++ b/resources/local/chainspec.toml.in @@ -178,7 +178,7 @@ block_max_approval_count = 2600 # Maximum block size in bytes including transactions contained by the block. 0 means unlimited. max_block_size = 5_242_880 # The upper limit of total gas of all transactions in a block. -block_gas_limit = 3_300_000_000_000 +block_gas_limit = 200_000_000_000 # The minimum amount in motes for a valid native transfer. native_transfer_minimum_motes = 2_500_000_000 # The maximum value to which `transaction_acceptor.timestamp_leeway` can be set in the config.toml file. @@ -204,9 +204,9 @@ vm_casper_v2 = false # [3] -> Transaction gas limit size in bytes for a given transaction in a certain lane # [4] -> The maximum number of transactions the lane can contain native_mint_lane = [0, 1024, 1024, 65_000_000_000, 650] -native_auction_lane = [1, 2048, 2048, 362_500_000_000, 145] -install_upgrade_lane = [2, 1_048_576, 2048, 1_000_000_000_000, 1] -wasm_lanes = [[3, 344_064, 1024, 500_000_000_000, 3], [4, 172_032, 1024, 50_000_000_000, 7], [5, 12_288, 512, 1_500_000_000, 15]] +native_auction_lane = [1, 2048, 2048, 2_500_000_000, 145] +install_upgrade_lane = [2, 1_048_576, 2048, 100_000_000_000, 1] +wasm_lanes = [[3, 344_064, 1024, 100_000_000_000, 3], [4, 172_032, 1024, 50_000_000_000, 7], [5, 12_288, 512, 1_500_000_000, 15]] [transactions.deploy] # The maximum number of Motes allowed to be spent during payment. 0 means unlimited. @@ -228,56 +228,56 @@ gas_per_byte = 1_117_587 [wasm.v1.opcode_costs] # Bit operations multiplier. -bit = 300 +bit = 35 # Arithmetic add operations multiplier. -add = 210 +add = 35 # Mul operations multiplier. -mul = 240 +mul = 35 # Div operations multiplier. -div = 320 +div = 35 # Memory load operation multiplier. -load = 2_500 +load = 35 # Memory store operation multiplier. -store = 4_700 +store = 35 # Const store operation multiplier. -const = 110 +const = 35 # Local operations multiplier. -local = 390 +local = 35 # Global operations multiplier. -global = 390 +global = 35 # Integer operations multiplier. -integer_comparison = 250 +integer_comparison = 35 # Conversion operations multiplier. -conversion = 420 +conversion = 35 # Unreachable operation multiplier. -unreachable = 270 +unreachable = 35 # Nop operation multiplier. -nop = 200 +nop = 35 # Get current memory operation multiplier. -current_memory = 290 +current_memory = 35 # Grow memory cost, per page (64kb). -grow_memory = 240_000 +grow_memory = 300 # Sign extension operations cost -sign = 300 +sign = 35 # Control flow operations multiplier. [wasm.v1.opcode_costs.control_flow] -block = 440 -loop = 440 -if = 440 -else = 440 -end = 440 -br = 35_000 -br_if = 35_000 -return = 440 -select = 440 -call = 68_000 -call_indirect = 68_000 -drop = 440 +block = 85 +loop = 85 +if = 35 +else = 35 +end = 35 +br = 555 +br_if = 170 +return = 35 +select = 35 +call = 75 +call_indirect = 90 +drop = 35 [wasm.v1.opcode_costs.control_flow.br_table] # Fixed cost per `br_table` opcode -cost = 35_000 +cost = 50 # Size of target labels in the `br_table` opcode will be multiplied by `size_multiplier` size_multiplier = 100 diff --git a/resources/production/chainspec.toml b/resources/production/chainspec.toml index bca88e2311..198c486674 100644 --- a/resources/production/chainspec.toml +++ b/resources/production/chainspec.toml @@ -185,7 +185,7 @@ block_max_approval_count = 2600 # Maximum block size in bytes including transactions contained by the block. 0 means unlimited. max_block_size = 5_242_880 # The upper limit of total gas of all transactions in a block. -block_gas_limit = 3_300_000_000_000 +block_gas_limit = 200_000_000_000 # The minimum amount in motes for a valid native transfer. native_transfer_minimum_motes = 2_500_000_000 # The maximum value to which `transaction_acceptor.timestamp_leeway` can be set in the config.toml file. @@ -212,9 +212,9 @@ vm_casper_v2 = false # [3] -> Transaction gas limit size in bytes for a given transaction in a certain lane # [4] -> The maximum number of transactions the lane can contain native_mint_lane = [0, 1024, 1024, 65_000_000_000, 650] -native_auction_lane = [1, 2048, 2048, 362_500_000_000, 145] -install_upgrade_lane = [2, 1_048_576, 2048, 1_000_000_000_000, 1] -wasm_lanes = [[3, 344_064, 1024, 500_000_000_000, 3], [4, 172_032, 1024, 50_000_000_000, 7], [5, 12_288, 512, 1_500_000_000, 15]] +native_auction_lane = [1, 2048, 2048, 2_500_000_000, 145] +install_upgrade_lane = [2, 1_048_576, 2048, 100_000_000_000, 1] +wasm_lanes = [[3, 344_064, 1024, 100_000_000_000, 3], [4, 172_032, 1024, 50_000_000_000, 7], [5, 12_288, 512, 1_500_000_000, 15]] [transactions.deploy] # The maximum number of Motes allowed to be spent during payment. 0 means unlimited. @@ -236,56 +236,56 @@ gas_per_byte = 1_117_587 [wasm.v1.opcode_costs] # Bit operations multiplier. -bit = 300 +bit = 35 # Arithmetic add operations multiplier. -add = 210 +add = 35 # Mul operations multiplier. -mul = 240 +mul = 35 # Div operations multiplier. -div = 320 +div = 35 # Memory load operation multiplier. -load = 2_500 +load = 35 # Memory store operation multiplier. -store = 4_700 +store = 35 # Const store operation multiplier. -const = 110 +const = 35 # Local operations multiplier. -local = 390 +local = 35 # Global operations multiplier. -global = 390 +global = 35 # Integer operations multiplier. -integer_comparison = 250 +integer_comparison = 35 # Conversion operations multiplier. -conversion = 420 +conversion = 35 # Unreachable operation multiplier. -unreachable = 270 +unreachable = 35 # Nop operation multiplier. -nop = 200 +nop = 35 # Get current memory operation multiplier. -current_memory = 290 +current_memory = 35 # Grow memory cost, per page (64kb). -grow_memory = 240_000 +grow_memory = 300 # Sign extension operations cost -sign = 300 +sign = 35 # Control flow operations multiplier. [wasm.v1.opcode_costs.control_flow] -block = 440 -loop = 440 -if = 440 -else = 440 -end = 440 -br = 35_000 -br_if = 35_000 -return = 440 -select = 440 -call = 68_000 -call_indirect = 68_000 -drop = 440 +block = 85 +loop = 85 +if = 35 +else = 35 +end = 35 +br = 555 +br_if = 170 +return = 35 +select = 35 +call = 75 +call_indirect = 90 +drop = 35 [wasm.v1.opcode_costs.control_flow.br_table] # Fixed cost per `br_table` opcode -cost = 35_000 +cost = 50 # Size of target labels in the `br_table` opcode will be multiplied by `size_multiplier` size_multiplier = 100 @@ -297,8 +297,8 @@ add_contract_version = { cost = 200, arguments = [0, 0, 0, 0, 120_000, 0, 0, 0, add_contract_version_with_message_topics = { cost = 200, arguments = [0, 0, 0, 0, 120_000, 0, 0, 0, 30_000, 0, 0] } add_package_version = { cost = 200, arguments = [0, 0, 0, 0, 120_000, 0, 0, 0, 30_000, 0, 0] } blake2b = { cost = 1_200_000, arguments = [0, 120_000, 0, 0] } -call_contract = { cost = 300_000_000, arguments = [0, 0, 0, 120_000, 0, 120_000, 0] } -call_versioned_contract = { cost = 300_000_000, arguments = [0, 0, 0, 0, 0, 120_000, 0, 120_000, 0] } +call_contract = { cost = 3000_000_000, arguments = [0, 0, 0, 120_000, 0, 120_000, 0] } +call_versioned_contract = { cost = 3000_000_000, arguments = [0, 0, 0, 0, 0, 120_000, 0, 120_000, 0] } create_contract_package_at_hash = { cost = 200, arguments = [0, 0] } create_contract_user_group = { cost = 200, arguments = [0, 0, 0, 0, 0, 0, 0, 0] } create_purse = { cost = 2_500_000_000, arguments = [0, 0] } diff --git a/types/src/chainspec/vm_config/opcode_costs.rs b/types/src/chainspec/vm_config/opcode_costs.rs index d17dcfcc37..42ae6aab71 100644 --- a/types/src/chainspec/vm_config/opcode_costs.rs +++ b/types/src/chainspec/vm_config/opcode_costs.rs @@ -14,66 +14,65 @@ use serde::{Deserialize, Serialize}; use crate::bytesrepr::{self, FromBytes, ToBytes}; /// Default cost of the `bit` Wasm opcode. -pub const DEFAULT_BIT_COST: u32 = 300; +pub const DEFAULT_BIT_COST: u32 = 35; /// Default cost of the `add` Wasm opcode. -pub const DEFAULT_ADD_COST: u32 = 210; +pub const DEFAULT_ADD_COST: u32 = 35; /// Default cost of the `mul` Wasm opcode. -pub const DEFAULT_MUL_COST: u32 = 240; +pub const DEFAULT_MUL_COST: u32 = 35; /// Default cost of the `div` Wasm opcode. -pub const DEFAULT_DIV_COST: u32 = 320; +pub const DEFAULT_DIV_COST: u32 = 35; /// Default cost of the `load` Wasm opcode. -pub const DEFAULT_LOAD_COST: u32 = 2_500; +pub const DEFAULT_LOAD_COST: u32 = 35; /// Default cost of the `store` Wasm opcode. -pub const DEFAULT_STORE_COST: u32 = 4_700; +pub const DEFAULT_STORE_COST: u32 = 35; /// Default cost of the `const` Wasm opcode. -pub const DEFAULT_CONST_COST: u32 = 110; +pub const DEFAULT_CONST_COST: u32 = 35; /// Default cost of the `local` Wasm opcode. -pub const DEFAULT_LOCAL_COST: u32 = 390; +pub const DEFAULT_LOCAL_COST: u32 = 35; /// Default cost of the `global` Wasm opcode. -pub const DEFAULT_GLOBAL_COST: u32 = 390; +pub const DEFAULT_GLOBAL_COST: u32 = 35; /// Default cost of the `integer_comparison` Wasm opcode. -pub const DEFAULT_INTEGER_COMPARISON_COST: u32 = 250; +pub const DEFAULT_INTEGER_COMPARISON_COST: u32 = 35; /// Default cost of the `conversion` Wasm opcode. -pub const DEFAULT_CONVERSION_COST: u32 = 420; +pub const DEFAULT_CONVERSION_COST: u32 = 35; /// Default cost of the `unreachable` Wasm opcode. -pub const DEFAULT_UNREACHABLE_COST: u32 = 270; +pub const DEFAULT_UNREACHABLE_COST: u32 = 35; /// Default cost of the `nop` Wasm opcode. -// TODO: This value is not researched. -pub const DEFAULT_NOP_COST: u32 = 200; +pub const DEFAULT_NOP_COST: u32 = 35; /// Default cost of the `current_memory` Wasm opcode. -pub const DEFAULT_CURRENT_MEMORY_COST: u32 = 290; +pub const DEFAULT_CURRENT_MEMORY_COST: u32 = 35; /// Default cost of the `grow_memory` Wasm opcode. -pub const DEFAULT_GROW_MEMORY_COST: u32 = 240_000; +pub const DEFAULT_GROW_MEMORY_COST: u32 = 300; /// Default cost of the `block` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_BLOCK_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_BLOCK_OPCODE: u32 = 85; /// Default cost of the `loop` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_LOOP_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_LOOP_OPCODE: u32 = 85; /// Default cost of the `if` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_IF_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_IF_OPCODE: u32 = 35; /// Default cost of the `else` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_ELSE_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_ELSE_OPCODE: u32 = 35; /// Default cost of the `end` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_END_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_END_OPCODE: u32 = 35; /// Default cost of the `br` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_BR_OPCODE: u32 = 35_000; +pub const DEFAULT_CONTROL_FLOW_BR_OPCODE: u32 = 555; /// Default cost of the `br_if` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_BR_IF_OPCODE: u32 = 35_000; +pub const DEFAULT_CONTROL_FLOW_BR_IF_OPCODE: u32 = 170; /// Default cost of the `return` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_RETURN_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_RETURN_OPCODE: u32 = 35; /// Default cost of the `select` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_SELECT_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_SELECT_OPCODE: u32 = 35; /// Default cost of the `call` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_CALL_OPCODE: u32 = 68_000; +pub const DEFAULT_CONTROL_FLOW_CALL_OPCODE: u32 = 75; /// Default cost of the `call_indirect` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_CALL_INDIRECT_OPCODE: u32 = 68_000; +pub const DEFAULT_CONTROL_FLOW_CALL_INDIRECT_OPCODE: u32 = 90; /// Default cost of the `drop` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_DROP_OPCODE: u32 = 440; +pub const DEFAULT_CONTROL_FLOW_DROP_OPCODE: u32 = 35; /// Default fixed cost of the `br_table` Wasm opcode. -pub const DEFAULT_CONTROL_FLOW_BR_TABLE_OPCODE: u32 = 35_000; +pub const DEFAULT_CONTROL_FLOW_BR_TABLE_OPCODE: u32 = 50; /// Default multiplier for the size of targets in `br_table` Wasm opcode. pub const DEFAULT_CONTROL_FLOW_BR_TABLE_MULTIPLIER: u32 = 100; /// Default cost of the sign extension opcodes -pub const DEFAULT_SIGN_COST: u32 = 300; +pub const DEFAULT_SIGN_COST: u32 = 35; /// Definition of a cost table for a Wasm `br_table` opcode. ///