diff --git a/Cargo.lock b/Cargo.lock index 13d11c9173..468c923c3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,6 +150,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -1596,6 +1597,7 @@ name = "revm-interpreter" version = "1.0.0" dependencies = [ "arbitrary", + "bitvec", "derive_more", "enumn", "proptest", @@ -1627,6 +1629,7 @@ version = "1.0.0" dependencies = [ "arbitrary", "auto_impl", + "bitvec", "bytes", "derive_more", "enumn", diff --git a/bins/revm-test/src/bin/analysis.rs b/bins/revm-test/src/bin/analysis.rs index e17aacbae9..568ef39da4 100644 --- a/bins/revm-test/src/bin/analysis.rs +++ b/bins/revm-test/src/bin/analysis.rs @@ -4,7 +4,7 @@ use bytes::Bytes; use revm::{ db::BenchmarkDB, interpreter::analysis::to_analysed, - primitives::{Bytecode, LondonSpec, TransactTo}, + primitives::{Bytecode, TransactTo}, }; extern crate alloc; @@ -29,7 +29,7 @@ fn main() { let bytecode_raw = Bytecode::new_raw(contract_data.clone()); let bytecode_checked = Bytecode::new_raw(contract_data.clone()).to_checked(); - let bytecode_analysed = to_analysed::(Bytecode::new_raw(contract_data)); + let bytecode_analysed = to_analysed(Bytecode::new_raw(contract_data)); evm.database(BenchmarkDB::new_bytecode(bytecode_raw)); diff --git a/bins/revm-test/src/bin/snailtracer.rs b/bins/revm-test/src/bin/snailtracer.rs index a649a9079b..fc80a152e4 100644 --- a/bins/revm-test/src/bin/snailtracer.rs +++ b/bins/revm-test/src/bin/snailtracer.rs @@ -13,7 +13,7 @@ pub fn simple_example() { // BenchmarkDB is dummy state that implements Database trait. let mut evm = revm::new(); - let bytecode = to_analysed::(Bytecode::new_raw(contract_data)); + let bytecode = to_analysed(Bytecode::new_raw(contract_data)); evm.database(BenchmarkDB::new_bytecode(bytecode.clone())); // execution globals block hash/gas_limit/coinbase/timestamp.. diff --git a/bins/revme/src/statetest/runner.rs b/bins/revme/src/statetest/runner.rs index 8f802d287c..f8eb4596ae 100644 --- a/bins/revme/src/statetest/runner.rs +++ b/bins/revme/src/statetest/runner.rs @@ -28,8 +28,8 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum TestError { - #[error(" Test:{spec_id:?}:{id}, Root missmatched, Expected: {expect:?} got:{got:?}")] - RootMissmatch { + #[error("Test: {id} ({spec_id:?}), root mismatched, expected: {expect:?} got: {got:?}")] + RootMismatch { spec_id: SpecId, id: usize, got: B256, @@ -287,7 +287,7 @@ pub fn execute_test_suit( let logs_root = log_rlp_hash(logs); if test.hash != state_root || test.logs != logs_root { println!( - "ROOTS mismath:\nstate_root:{:?}:{state_root:?}\nlogs_root:{:?}:{logs_root:?}", + "Roots did not match:\nState root: wanted {:?}, got {state_root:?}\nLogs root: wanted {:?}, got {logs_root:?}", test.hash, test.logs ); let mut database_cloned = database.clone(); @@ -319,9 +319,9 @@ pub fn execute_test_suit( println!("Output: {out:?} {path:?} UNIT_TEST:{name}\n"); } } - println!("\nApplied state:{db:?}\n"); - println!("\nStateroot: {state_root:?}\n"); - return Err(TestError::RootMissmatch { + println!("\nApplied state:\n{db:#?}\n"); + println!("\nState root: {state_root:?}\n"); + return Err(TestError::RootMismatch { spec_id: env.cfg.spec_id, id, got: state_root, diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 8207590126..b7cd749a13 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -11,6 +11,7 @@ readme = "../../README.md" [dependencies] revm-primitives = { path = "../primitives", version="1.0.0", default-features = false } +bitvec = { version = "1", default-features = false } #utility derive_more = "0.99" @@ -45,10 +46,11 @@ optional_balance_check = ["revm-primitives/optional_balance_check"] optional_block_gas_limit = ["revm-primitives/optional_block_gas_limit"] optional_eip3607 = ["revm-primitives/optional_eip3607"] optional_gas_refund = ["revm-primitives/optional_gas_refund"] -std = ["revm-primitives/std"] +std = ["revm-primitives/std", "bitvec/std"] serde = [ "dep:serde", "revm-primitives/serde", + "bitvec/serde", ] arbitrary = [ "dep:arbitrary", diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 4697281193..c63ce251a8 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -111,11 +111,16 @@ pub fn extcodecopy_cost(len: u64, is_cold: bool) -> Option { let wordd = len / 32; let wordr = len % 32; - let base_gas: u64 = if SPEC::enabled(BERLIN) && is_cold { - // WARM_STORAGE_READ_COST is already calculated - COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST + let base_gas: u64 = if SPEC::enabled(BERLIN) { + if is_cold { + COLD_ACCOUNT_ACCESS_COST + } else { + WARM_STORAGE_READ_COST + } + } else if SPEC::enabled(TANGERINE) { + 700 } else { - 0 + 20 }; base_gas.checked_add(COPY.checked_mul(if wordr == 0 { wordd } else { wordd + 1 })?) } diff --git a/crates/interpreter/src/instructions/arithmetic.rs b/crates/interpreter/src/instructions/arithmetic.rs index aa139139c3..188716c5e3 100644 --- a/crates/interpreter/src/instructions/arithmetic.rs +++ b/crates/interpreter/src/instructions/arithmetic.rs @@ -6,36 +6,43 @@ use crate::{ }; pub fn wrapped_add(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = op1.wrapping_add(*op2); } pub fn wrapping_mul(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::LOW); pop_top!(interpreter, op1, op2); *op2 = op1.wrapping_mul(*op2); } pub fn wrapping_sub(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = op1.wrapping_sub(*op2); } pub fn div(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::LOW); pop_top!(interpreter, op1, op2); *op2 = op1.checked_div(*op2).unwrap_or_default() } pub fn sdiv(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::LOW); pop_top!(interpreter, op1, op2); *op2 = i256_div(op1, *op2); } pub fn rem(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::LOW); pop_top!(interpreter, op1, op2); *op2 = op1.checked_rem(*op2).unwrap_or_default() } pub fn smod(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::LOW); pop_top!(interpreter, op1, op2); if *op2 != U256::ZERO { *op2 = i256_mod(op1, *op2) @@ -43,11 +50,13 @@ pub fn smod(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn addmod(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::MID); pop_top!(interpreter, op1, op2, op3); *op3 = op1.add_mod(op2, *op3) } pub fn mulmod(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::MID); pop_top!(interpreter, op1, op2, op3); *op3 = op1.mul_mod(op2, *op3) } @@ -74,6 +83,7 @@ pub fn eval_exp(interpreter: &mut Interpreter, _host: &mut dyn Host) /// `b == 0` then the yellow paper says the output should start with all zeros, then end with /// bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`. pub fn signextend(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::LOW); pop_top!(interpreter, op1, op2); if op1 < U256::from(32) { // `low_u32` works since op1 < 32 diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 066e7b6b74..c717e0e168 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -1,5 +1,6 @@ use super::i256::{i256_cmp, i256_sign, two_compl, Sign}; use crate::{ + gas, primitives::SpecId::CONSTANTINOPLE, primitives::{Spec, U256}, Host, InstructionResult, Interpreter, @@ -8,6 +9,7 @@ use core::cmp::Ordering; use core::ops::{BitAnd, BitOr, BitXor}; pub fn lt(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = if op1.lt(op2) { U256::from(1) @@ -17,6 +19,7 @@ pub fn lt(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn gt(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = if op1.gt(op2) { U256::from(1) @@ -26,6 +29,7 @@ pub fn gt(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn slt(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = if i256_cmp(op1, *op2) == Ordering::Less { U256::from(1) @@ -35,6 +39,7 @@ pub fn slt(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn sgt(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = if i256_cmp(op1, *op2) == Ordering::Greater { U256::from(1) @@ -44,6 +49,7 @@ pub fn sgt(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn eq(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = if op1.eq(op2) { U256::from(1) @@ -53,6 +59,7 @@ pub fn eq(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn iszero(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1); *op1 = if *op1 == U256::ZERO { U256::from(1) @@ -61,24 +68,29 @@ pub fn iszero(interpreter: &mut Interpreter, _host: &mut dyn Host) { }; } pub fn bitand(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = op1.bitand(*op2); } pub fn bitor(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = op1.bitor(*op2); } pub fn bitxor(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 = op1.bitxor(*op2); } pub fn not(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1); *op1 = !*op1; } pub fn byte(interpreter: &mut Interpreter, _host: &mut dyn Host) { + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); let mut ret = U256::ZERO; @@ -98,6 +110,7 @@ pub fn byte(interpreter: &mut Interpreter, _host: &mut dyn Host) { pub fn shl(interpreter: &mut Interpreter, _host: &mut dyn Host) { // EIP-145: Bitwise shifting instructions in EVM check!(interpreter, SPEC::enabled(CONSTANTINOPLE)); + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 <<= as_usize_saturated!(op1); } @@ -105,6 +118,7 @@ pub fn shl(interpreter: &mut Interpreter, _host: &mut dyn Host) { pub fn shr(interpreter: &mut Interpreter, _host: &mut dyn Host) { // EIP-145: Bitwise shifting instructions in EVM check!(interpreter, SPEC::enabled(CONSTANTINOPLE)); + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); *op2 >>= as_usize_saturated!(op1); } @@ -112,6 +126,7 @@ pub fn shr(interpreter: &mut Interpreter, _host: &mut dyn Host) { pub fn sar(interpreter: &mut Interpreter, _host: &mut dyn Host) { // EIP-145: Bitwise shifting instructions in EVM check!(interpreter, SPEC::enabled(CONSTANTINOPLE)); + gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); let value_sign = i256_sign::(op2); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 8d3213e661..ccb532f6c5 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -4,7 +4,7 @@ use crate::{ }; pub fn jump(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::MID); + gas!(interpreter, gas::MID); pop!(interpreter, dest); let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidJump); if interpreter.contract.is_valid_jump(dest) { @@ -18,7 +18,7 @@ pub fn jump(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn jumpi(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::HIGH); + gas!(interpreter, gas::HIGH); pop!(interpreter, dest, value); if value != U256::ZERO { let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidJump); @@ -30,21 +30,15 @@ pub fn jumpi(interpreter: &mut Interpreter, _host: &mut dyn Host) { } else { interpreter.instruction_result = InstructionResult::InvalidJump } - } else if let Some(ret) = interpreter.add_next_gas_block(interpreter.program_counter() - 1) { - // if we are not doing jump, add next gas block. - interpreter.instruction_result = ret; } } pub fn jumpdest(interpreter: &mut Interpreter, _host: &mut dyn Host) { gas!(interpreter, gas::JUMPDEST); - if let Some(ret) = interpreter.add_next_gas_block(interpreter.program_counter() - 1) { - interpreter.instruction_result = ret; - } } pub fn pc(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, U256::from(interpreter.program_counter() - 1)); } diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 99596e8bf4..cfc62c5814 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -32,9 +32,9 @@ pub fn balance(interpreter: &mut Interpreter, host: &mut dyn Host) { } pub fn selfbalance(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::LOW); // EIP-1884: Repricing for trie-size-dependent opcodes check!(interpreter, SPEC::enabled(ISTANBUL)); + gas!(interpreter, gas::LOW); let ret = host.balance(interpreter.contract.address); if ret.is_none() { interpreter.instruction_result = InstructionResult::FatalExternalError; @@ -52,12 +52,19 @@ pub fn extcodesize(interpreter: &mut Interpreter, host: &mut dyn Hos return; } let (code, is_cold) = ret.unwrap(); - if SPEC::enabled(BERLIN) && is_cold { - // WARM_STORAGE_READ_COST is already calculated in gas block + if SPEC::enabled(BERLIN) { gas!( interpreter, - COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST + if is_cold { + COLD_ACCOUNT_ACCESS_COST + } else { + WARM_STORAGE_READ_COST + } ); + } else if SPEC::enabled(TANGERINE) { + gas!(interpreter, 700); + } else { + gas!(interpreter, 20); } push!(interpreter, U256::from(code.len())); @@ -72,12 +79,19 @@ pub fn extcodehash(interpreter: &mut Interpreter, host: &mut dyn Hos return; } let (code_hash, is_cold) = ret.unwrap(); - if SPEC::enabled(BERLIN) && is_cold { - // WARM_STORAGE_READ_COST is already calculated in gas block + if SPEC::enabled(BERLIN) { gas!( interpreter, - COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST + if is_cold { + COLD_ACCOUNT_ACCESS_COST + } else { + WARM_STORAGE_READ_COST + } ); + } else if SPEC::enabled(ISTANBUL) { + gas!(interpreter, 700); + } else { + gas!(interpreter, 400); } push_b256!(interpreter, code_hash); } @@ -116,7 +130,7 @@ pub fn extcodecopy(interpreter: &mut Interpreter, host: &mut dyn Hos } pub fn blockhash(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BLOCKHASH); + gas!(interpreter, gas::BLOCKHASH); pop_top!(interpreter, number); if let Some(diff) = host.env().block.number.checked_sub(*number) { @@ -163,9 +177,6 @@ pub fn sstore(interpreter: &mut Interpreter, host: &mut dyn Host) { gas::sstore_cost::(original, old, new, remaining_gas, is_cold) }); refund!(interpreter, gas::sstore_refund::(original, old, new)); - if let Some(ret) = interpreter.add_next_gas_block(interpreter.program_counter() - 1) { - interpreter.instruction_result = ret; - } } pub fn log(interpreter: &mut Interpreter, host: &mut dyn Host) { @@ -303,15 +314,11 @@ pub fn create( } InstructionResult::FatalExternalError => { interpreter.instruction_result = InstructionResult::FatalExternalError; - return; } _ => { push_b256!(interpreter, B256::zero()); } } - if let Some(ret) = interpreter.add_next_gas_block(interpreter.program_counter() - 1) { - interpreter.instruction_result = ret; - } } pub fn call(interpreter: &mut Interpreter, host: &mut dyn Host) { @@ -508,13 +515,9 @@ pub fn call_inner( } InstructionResult::FatalExternalError => { interpreter.instruction_result = InstructionResult::FatalExternalError; - return; } _ => { push!(interpreter, U256::ZERO); } } - if let Some(ret) = interpreter.add_next_gas_block(interpreter.program_counter() - 1) { - interpreter.instruction_result = ret; - } } diff --git a/crates/interpreter/src/instructions/host_env.rs b/crates/interpreter/src/instructions/host_env.rs index 24a370d747..e3d7d5fc6a 100644 --- a/crates/interpreter/src/instructions/host_env.rs +++ b/crates/interpreter/src/instructions/host_env.rs @@ -1,31 +1,31 @@ use crate::{ - interpreter::Interpreter, primitives::Spec, primitives::SpecId::*, Host, InstructionResult, + gas, interpreter::Interpreter, primitives::Spec, primitives::SpecId::*, Host, InstructionResult, }; pub fn chainid(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); // EIP-1344: ChainID opcode check!(interpreter, SPEC::enabled(ISTANBUL)); + gas!(interpreter, gas::BASE); push!(interpreter, host.env().cfg.chain_id); } pub fn coinbase(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push_b256!(interpreter, host.env().block.coinbase.into()); } pub fn timestamp(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, host.env().block.timestamp); } pub fn number(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, host.env().block.number); } pub fn difficulty(interpreter: &mut Interpreter, host: &mut H) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); if SPEC::enabled(MERGE) { push_b256!(interpreter, host.env().block.prevrandao.unwrap()); } else { @@ -34,23 +34,23 @@ pub fn difficulty(interpreter: &mut Interpreter, host: &mut } pub fn gaslimit(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, host.env().block.gas_limit); } pub fn gasprice(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, host.env().effective_gas_price()); } pub fn basefee(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); // EIP-3198: BASEFEE opcode check!(interpreter, SPEC::enabled(LONDON)); push!(interpreter, host.env().block.basefee); } pub fn origin(interpreter: &mut Interpreter, host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push_b256!(interpreter, host.env().tx.caller.into()); } diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index f40f4561bb..358d36ce38 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -1,7 +1,7 @@ -use crate::{interpreter::Interpreter, primitives::U256, Host, InstructionResult}; +use crate::{gas, interpreter::Interpreter, primitives::U256, Host, InstructionResult}; pub fn mload(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); pop!(interpreter, index); let index = as_usize_or_fail!(interpreter, index, InstructionResult::InvalidOperandOOG); memory_resize!(interpreter, index, 32); @@ -14,7 +14,7 @@ pub fn mload(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn mstore(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); pop!(interpreter, index, value); let index = as_usize_or_fail!(interpreter, index, InstructionResult::InvalidOperandOOG); memory_resize!(interpreter, index, 32); @@ -22,7 +22,7 @@ pub fn mstore(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn mstore8(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); pop!(interpreter, index, value); let index = as_usize_or_fail!(interpreter, index, InstructionResult::InvalidOperandOOG); memory_resize!(interpreter, index, 1); @@ -32,6 +32,6 @@ pub fn mstore8(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn msize(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, U256::from(interpreter.memory.effective_len())); } diff --git a/crates/interpreter/src/instructions/opcode.rs b/crates/interpreter/src/instructions/opcode.rs index 74dbf019ed..412ed5a276 100644 --- a/crates/interpreter/src/instructions/opcode.rs +++ b/crates/interpreter/src/instructions/opcode.rs @@ -1,6 +1,3 @@ -use crate::gas; -use crate::primitives::SpecId; - #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct OpCode(u8); @@ -171,471 +168,6 @@ impl OpCode { } } -const JUMP_MASK: u32 = 0x80000000; -const GAS_BLOCK_END_MASK: u32 = 0x40000000; -const IS_PUSH_MASK: u32 = 0x20000000; -const GAS_MASK: u32 = 0x1FFFFFFF; - -#[derive(Debug)] -pub struct OpInfo { - /// Data contains few information packed inside u32: - /// IS_JUMP (1bit) | IS_GAS_BLOCK_END (1bit) | IS_PUSH (1bit) | gas (29bits) - data: u32, -} - -impl OpInfo { - #[inline(always)] - pub fn is_jump(&self) -> bool { - self.data & JUMP_MASK == JUMP_MASK - } - #[inline(always)] - pub fn is_gas_block_end(&self) -> bool { - self.data & GAS_BLOCK_END_MASK == GAS_BLOCK_END_MASK - } - #[inline(always)] - pub fn is_push(&self) -> bool { - self.data & IS_PUSH_MASK == IS_PUSH_MASK - } - - #[inline(always)] - pub fn get_gas(&self) -> u32 { - self.data & GAS_MASK - } - - pub const fn none() -> Self { - Self { data: 0 } - } - - pub const fn gas_block_end(gas: u64) -> Self { - Self { - data: gas as u32 | GAS_BLOCK_END_MASK, - } - } - pub const fn dynamic_gas() -> Self { - Self { data: 0 } - } - - pub const fn gas(gas: u64) -> Self { - Self { data: gas as u32 } - } - pub const fn push_opcode() -> Self { - Self { - data: gas::VERYLOW as u32 | IS_PUSH_MASK, - } - } - - pub const fn jumpdest() -> Self { - Self { - data: JUMP_MASK | GAS_BLOCK_END_MASK, - } - } -} - -macro_rules! gas_opcodee { - ($name:ident, $spec_id:expr) => { - const $name: &'static [OpInfo; 256] = &[ - /* 0x00 STOP */ OpInfo::gas_block_end(0), - /* 0x01 ADD */ OpInfo::gas(gas::VERYLOW), - /* 0x02 MUL */ OpInfo::gas(gas::LOW), - /* 0x03 SUB */ OpInfo::gas(gas::VERYLOW), - /* 0x04 DIV */ OpInfo::gas(gas::LOW), - /* 0x05 SDIV */ OpInfo::gas(gas::LOW), - /* 0x06 MOD */ OpInfo::gas(gas::LOW), - /* 0x07 SMOD */ OpInfo::gas(gas::LOW), - /* 0x08 ADDMOD */ OpInfo::gas(gas::MID), - /* 0x09 MULMOD */ OpInfo::gas(gas::MID), - /* 0x0a EXP */ OpInfo::dynamic_gas(), - /* 0x0b SIGNEXTEND */ OpInfo::gas(gas::LOW), - /* 0x0c */ OpInfo::none(), - /* 0x0d */ OpInfo::none(), - /* 0x0e */ OpInfo::none(), - /* 0x0f */ OpInfo::none(), - /* 0x10 LT */ OpInfo::gas(gas::VERYLOW), - /* 0x11 GT */ OpInfo::gas(gas::VERYLOW), - /* 0x12 SLT */ OpInfo::gas(gas::VERYLOW), - /* 0x13 SGT */ OpInfo::gas(gas::VERYLOW), - /* 0x14 EQ */ OpInfo::gas(gas::VERYLOW), - /* 0x15 ISZERO */ OpInfo::gas(gas::VERYLOW), - /* 0x16 AND */ OpInfo::gas(gas::VERYLOW), - /* 0x17 OR */ OpInfo::gas(gas::VERYLOW), - /* 0x18 XOR */ OpInfo::gas(gas::VERYLOW), - /* 0x19 NOT */ OpInfo::gas(gas::VERYLOW), - /* 0x1a BYTE */ OpInfo::gas(gas::VERYLOW), - /* 0x1b SHL */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::CONSTANTINOPLE) { - gas::VERYLOW - } else { - 0 - }), - /* 0x1c SHR */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::CONSTANTINOPLE) { - gas::VERYLOW - } else { - 0 - }), - /* 0x1d SAR */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::CONSTANTINOPLE) { - gas::VERYLOW - } else { - 0 - }), - /* 0x1e */ OpInfo::none(), - /* 0x1f */ OpInfo::none(), - /* 0x20 SHA3 */ OpInfo::dynamic_gas(), - /* 0x21 */ OpInfo::none(), - /* 0x22 */ OpInfo::none(), - /* 0x23 */ OpInfo::none(), - /* 0x24 */ OpInfo::none(), - /* 0x25 */ OpInfo::none(), - /* 0x26 */ OpInfo::none(), - /* 0x27 */ OpInfo::none(), - /* 0x28 */ OpInfo::none(), - /* 0x29 */ OpInfo::none(), - /* 0x2a */ OpInfo::none(), - /* 0x2b */ OpInfo::none(), - /* 0x2c */ OpInfo::none(), - /* 0x2d */ OpInfo::none(), - /* 0x2e */ OpInfo::none(), - /* 0x2f */ OpInfo::none(), - /* 0x30 ADDRESS */ OpInfo::gas(gas::BASE), - /* 0x31 BALANCE */ OpInfo::dynamic_gas(), - /* 0x32 ORIGIN */ OpInfo::gas(gas::BASE), - /* 0x33 CALLER */ OpInfo::gas(gas::BASE), - /* 0x34 CALLVALUE */ OpInfo::gas(gas::BASE), - /* 0x35 CALLDATALOAD */ OpInfo::gas(gas::VERYLOW), - /* 0x36 CALLDATASIZE */ OpInfo::gas(gas::BASE), - /* 0x37 CALLDATACOPY */ OpInfo::dynamic_gas(), - /* 0x38 CODESIZE */ OpInfo::gas(gas::BASE), - /* 0x39 CODECOPY */ OpInfo::dynamic_gas(), - /* 0x3a GASPRICE */ OpInfo::gas(gas::BASE), - /* 0x3b EXTCODESIZE */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::BERLIN) { - gas::WARM_STORAGE_READ_COST // add only part of gas - } else if SpecId::enabled($spec_id, SpecId::TANGERINE) { - 700 - } else { - 20 - }), - /* 0x3c EXTCODECOPY */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::BERLIN) { - gas::WARM_STORAGE_READ_COST // add only part of gas - } else if SpecId::enabled($spec_id, SpecId::TANGERINE) { - 700 - } else { - 20 - }), - /* 0x3d RETURNDATASIZE */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::BYZANTIUM) { - gas::BASE - } else { - 0 - }), - /* 0x3e RETURNDATACOPY */ OpInfo::dynamic_gas(), - /* 0x3f EXTCODEHASH */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::BERLIN) { - gas::WARM_STORAGE_READ_COST // add only part of gas - } else if SpecId::enabled($spec_id, SpecId::ISTANBUL) { - 700 - } else if SpecId::enabled($spec_id, SpecId::PETERSBURG) { - // constantinople - 400 - } else { - 0 // not enabled - }), - /* 0x40 BLOCKHASH */ OpInfo::gas(gas::BLOCKHASH), - /* 0x41 COINBASE */ OpInfo::gas(gas::BASE), - /* 0x42 TIMESTAMP */ OpInfo::gas(gas::BASE), - /* 0x43 NUMBER */ OpInfo::gas(gas::BASE), - /* 0x44 DIFFICULTY */ OpInfo::gas(gas::BASE), - /* 0x45 GASLIMIT */ OpInfo::gas(gas::BASE), - /* 0x46 CHAINID */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::ISTANBUL) { - gas::BASE - } else { - 0 - }), - /* 0x47 SELFBALANCE */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::ISTANBUL) { - gas::LOW - } else { - 0 - }), - /* 0x48 BASEFEE */ - OpInfo::gas(if SpecId::enabled($spec_id, SpecId::LONDON) { - gas::BASE - } else { - 0 - }), - /* 0x49 */ OpInfo::none(), - /* 0x4a */ OpInfo::none(), - /* 0x4b */ OpInfo::none(), - /* 0x4c */ OpInfo::none(), - /* 0x4d */ OpInfo::none(), - /* 0x4e */ OpInfo::none(), - /* 0x4f */ OpInfo::none(), - /* 0x50 POP */ OpInfo::gas(gas::BASE), - /* 0x51 MLOAD */ OpInfo::gas(gas::VERYLOW), - /* 0x52 MSTORE */ OpInfo::gas(gas::VERYLOW), - /* 0x53 MSTORE8 */ OpInfo::gas(gas::VERYLOW), - /* 0x54 SLOAD */ OpInfo::dynamic_gas(), - /* 0x55 SSTORE */ OpInfo::gas_block_end(0), - /* 0x56 JUMP */ OpInfo::gas_block_end(gas::MID), - /* 0x57 JUMPI */ OpInfo::gas_block_end(gas::HIGH), - /* 0x58 PC */ OpInfo::gas(gas::BASE), - /* 0x59 MSIZE */ OpInfo::gas(gas::BASE), - /* 0x5a GAS */ OpInfo::gas_block_end(gas::BASE), - /* 0x5b JUMPDEST */ - // gas::JUMPDEST gas is calculated in function call, - OpInfo::jumpdest(), - /* 0x5c */ OpInfo::none(), - /* 0x5d */ OpInfo::none(), - /* 0x5e */ OpInfo::none(), - /* 0x5f PUSH0 */ OpInfo::gas(gas::BASE), - /* 0x60 PUSH1 */ OpInfo::push_opcode(), - /* 0x61 PUSH2 */ OpInfo::push_opcode(), - /* 0x62 PUSH3 */ OpInfo::push_opcode(), - /* 0x63 PUSH4 */ OpInfo::push_opcode(), - /* 0x64 PUSH5 */ OpInfo::push_opcode(), - /* 0x65 PUSH6 */ OpInfo::push_opcode(), - /* 0x66 PUSH7 */ OpInfo::push_opcode(), - /* 0x67 PUSH8 */ OpInfo::push_opcode(), - /* 0x68 PUSH9 */ OpInfo::push_opcode(), - /* 0x69 PUSH10 */ OpInfo::push_opcode(), - /* 0x6a PUSH11 */ OpInfo::push_opcode(), - /* 0x6b PUSH12 */ OpInfo::push_opcode(), - /* 0x6c PUSH13 */ OpInfo::push_opcode(), - /* 0x6d PUSH14 */ OpInfo::push_opcode(), - /* 0x6e PUSH15 */ OpInfo::push_opcode(), - /* 0x6f PUSH16 */ OpInfo::push_opcode(), - /* 0x70 PUSH17 */ OpInfo::push_opcode(), - /* 0x71 PUSH18 */ OpInfo::push_opcode(), - /* 0x72 PUSH19 */ OpInfo::push_opcode(), - /* 0x73 PUSH20 */ OpInfo::push_opcode(), - /* 0x74 PUSH21 */ OpInfo::push_opcode(), - /* 0x75 PUSH22 */ OpInfo::push_opcode(), - /* 0x76 PUSH23 */ OpInfo::push_opcode(), - /* 0x77 PUSH24 */ OpInfo::push_opcode(), - /* 0x78 PUSH25 */ OpInfo::push_opcode(), - /* 0x79 PUSH26 */ OpInfo::push_opcode(), - /* 0x7a PUSH27 */ OpInfo::push_opcode(), - /* 0x7b PUSH28 */ OpInfo::push_opcode(), - /* 0x7c PUSH29 */ OpInfo::push_opcode(), - /* 0x7d PUSH30 */ OpInfo::push_opcode(), - /* 0x7e PUSH31 */ OpInfo::push_opcode(), - /* 0x7f PUSH32 */ OpInfo::push_opcode(), - /* 0x80 DUP1 */ OpInfo::gas(gas::VERYLOW), - /* 0x81 DUP2 */ OpInfo::gas(gas::VERYLOW), - /* 0x82 DUP3 */ OpInfo::gas(gas::VERYLOW), - /* 0x83 DUP4 */ OpInfo::gas(gas::VERYLOW), - /* 0x84 DUP5 */ OpInfo::gas(gas::VERYLOW), - /* 0x85 DUP6 */ OpInfo::gas(gas::VERYLOW), - /* 0x86 DUP7 */ OpInfo::gas(gas::VERYLOW), - /* 0x87 DUP8 */ OpInfo::gas(gas::VERYLOW), - /* 0x88 DUP9 */ OpInfo::gas(gas::VERYLOW), - /* 0x89 DUP10 */ OpInfo::gas(gas::VERYLOW), - /* 0x8a DUP11 */ OpInfo::gas(gas::VERYLOW), - /* 0x8b DUP12 */ OpInfo::gas(gas::VERYLOW), - /* 0x8c DUP13 */ OpInfo::gas(gas::VERYLOW), - /* 0x8d DUP14 */ OpInfo::gas(gas::VERYLOW), - /* 0x8e DUP15 */ OpInfo::gas(gas::VERYLOW), - /* 0x8f DUP16 */ OpInfo::gas(gas::VERYLOW), - /* 0x90 SWAP1 */ OpInfo::gas(gas::VERYLOW), - /* 0x91 SWAP2 */ OpInfo::gas(gas::VERYLOW), - /* 0x92 SWAP3 */ OpInfo::gas(gas::VERYLOW), - /* 0x93 SWAP4 */ OpInfo::gas(gas::VERYLOW), - /* 0x94 SWAP5 */ OpInfo::gas(gas::VERYLOW), - /* 0x95 SWAP6 */ OpInfo::gas(gas::VERYLOW), - /* 0x96 SWAP7 */ OpInfo::gas(gas::VERYLOW), - /* 0x97 SWAP8 */ OpInfo::gas(gas::VERYLOW), - /* 0x98 SWAP9 */ OpInfo::gas(gas::VERYLOW), - /* 0x99 SWAP10 */ OpInfo::gas(gas::VERYLOW), - /* 0x9a SWAP11 */ OpInfo::gas(gas::VERYLOW), - /* 0x9b SWAP12 */ OpInfo::gas(gas::VERYLOW), - /* 0x9c SWAP13 */ OpInfo::gas(gas::VERYLOW), - /* 0x9d SWAP14 */ OpInfo::gas(gas::VERYLOW), - /* 0x9e SWAP15 */ OpInfo::gas(gas::VERYLOW), - /* 0x9f SWAP16 */ OpInfo::gas(gas::VERYLOW), - /* 0xa0 LOG0 */ OpInfo::dynamic_gas(), - /* 0xa1 LOG1 */ OpInfo::dynamic_gas(), - /* 0xa2 LOG2 */ OpInfo::dynamic_gas(), - /* 0xa3 LOG3 */ OpInfo::dynamic_gas(), - /* 0xa4 LOG4 */ OpInfo::dynamic_gas(), - /* 0xa5 */ OpInfo::none(), - /* 0xa6 */ OpInfo::none(), - /* 0xa7 */ OpInfo::none(), - /* 0xa8 */ OpInfo::none(), - /* 0xa9 */ OpInfo::none(), - /* 0xaa */ OpInfo::none(), - /* 0xab */ OpInfo::none(), - /* 0xac */ OpInfo::none(), - /* 0xad */ OpInfo::none(), - /* 0xae */ OpInfo::none(), - /* 0xaf */ OpInfo::none(), - /* 0xb0 */ OpInfo::none(), - /* 0xb1 */ OpInfo::none(), - /* 0xb2 */ OpInfo::none(), - /* 0xb3 */ OpInfo::none(), - /* 0xb4 */ OpInfo::none(), - /* 0xb5 */ OpInfo::none(), - /* 0xb6 */ OpInfo::none(), - /* 0xb7 */ OpInfo::none(), - /* 0xb8 */ OpInfo::none(), - /* 0xb9 */ OpInfo::none(), - /* 0xba */ OpInfo::none(), - /* 0xbb */ OpInfo::none(), - /* 0xbc */ OpInfo::none(), - /* 0xbd */ OpInfo::none(), - /* 0xbe */ OpInfo::none(), - /* 0xbf */ OpInfo::none(), - /* 0xc0 */ OpInfo::none(), - /* 0xc1 */ OpInfo::none(), - /* 0xc2 */ OpInfo::none(), - /* 0xc3 */ OpInfo::none(), - /* 0xc4 */ OpInfo::none(), - /* 0xc5 */ OpInfo::none(), - /* 0xc6 */ OpInfo::none(), - /* 0xc7 */ OpInfo::none(), - /* 0xc8 */ OpInfo::none(), - /* 0xc9 */ OpInfo::none(), - /* 0xca */ OpInfo::none(), - /* 0xcb */ OpInfo::none(), - /* 0xcc */ OpInfo::none(), - /* 0xcd */ OpInfo::none(), - /* 0xce */ OpInfo::none(), - /* 0xcf */ OpInfo::none(), - /* 0xd0 */ OpInfo::none(), - /* 0xd1 */ OpInfo::none(), - /* 0xd2 */ OpInfo::none(), - /* 0xd3 */ OpInfo::none(), - /* 0xd4 */ OpInfo::none(), - /* 0xd5 */ OpInfo::none(), - /* 0xd6 */ OpInfo::none(), - /* 0xd7 */ OpInfo::none(), - /* 0xd8 */ OpInfo::none(), - /* 0xd9 */ OpInfo::none(), - /* 0xda */ OpInfo::none(), - /* 0xdb */ OpInfo::none(), - /* 0xdc */ OpInfo::none(), - /* 0xdd */ OpInfo::none(), - /* 0xde */ OpInfo::none(), - /* 0xdf */ OpInfo::none(), - /* 0xe0 */ OpInfo::none(), - /* 0xe1 */ OpInfo::none(), - /* 0xe2 */ OpInfo::none(), - /* 0xe3 */ OpInfo::none(), - /* 0xe4 */ OpInfo::none(), - /* 0xe5 */ OpInfo::none(), - /* 0xe6 */ OpInfo::none(), - /* 0xe7 */ OpInfo::none(), - /* 0xe8 */ OpInfo::none(), - /* 0xe9 */ OpInfo::none(), - /* 0xea */ OpInfo::none(), - /* 0xeb */ OpInfo::none(), - /* 0xec */ OpInfo::none(), - /* 0xed */ OpInfo::none(), - /* 0xee */ OpInfo::none(), - /* 0xef */ OpInfo::none(), - /* 0xf0 CREATE */ OpInfo::gas_block_end(0), - /* 0xf1 CALL */ OpInfo::gas_block_end(0), - /* 0xf2 CALLCODE */ OpInfo::gas_block_end(0), - /* 0xf3 RETURN */ OpInfo::gas_block_end(0), - /* 0xf4 DELEGATECALL */ OpInfo::gas_block_end(0), - /* 0xf5 CREATE2 */ OpInfo::gas_block_end(0), - /* 0xf6 */ OpInfo::none(), - /* 0xf7 */ OpInfo::none(), - /* 0xf8 */ OpInfo::none(), - /* 0xf9 */ OpInfo::none(), - /* 0xfa STATICCALL */ OpInfo::gas_block_end(0), - /* 0xfb */ OpInfo::none(), - /* 0xfc */ OpInfo::none(), - /* 0xfd REVERT */ OpInfo::gas_block_end(0), - /* 0xfe INVALID */ OpInfo::gas_block_end(0), - /* 0xff SELFDESTRUCT */ OpInfo::gas_block_end(0), - ]; - }; -} - -pub const fn spec_opcode_gas(spec_id: SpecId) -> &'static [OpInfo; 256] { - match spec_id { - SpecId::FRONTIER => { - gas_opcodee!(FRONTIER, SpecId::FRONTIER); - FRONTIER - } - SpecId::FRONTIER_THAWING => { - gas_opcodee!(FRONTIER_THAWING, SpecId::FRONTIER_THAWING); - FRONTIER_THAWING - } - SpecId::HOMESTEAD => { - gas_opcodee!(HOMESTEAD, SpecId::HOMESTEAD); - HOMESTEAD - } - SpecId::DAO_FORK => { - gas_opcodee!(DAO_FORK, SpecId::DAO_FORK); - DAO_FORK - } - SpecId::TANGERINE => { - gas_opcodee!(TANGERINE, SpecId::TANGERINE); - TANGERINE - } - SpecId::SPURIOUS_DRAGON => { - gas_opcodee!(SPURIOUS_DRAGON, SpecId::SPURIOUS_DRAGON); - SPURIOUS_DRAGON - } - SpecId::BYZANTIUM => { - gas_opcodee!(BYZANTIUM, SpecId::BYZANTIUM); - BYZANTIUM - } - SpecId::CONSTANTINOPLE => { - gas_opcodee!(CONSTANTINOPLE, SpecId::CONSTANTINOPLE); - CONSTANTINOPLE - } - SpecId::PETERSBURG => { - gas_opcodee!(PETERSBURG, SpecId::PETERSBURG); - PETERSBURG - } - SpecId::ISTANBUL => { - gas_opcodee!(ISTANBUL, SpecId::ISTANBUL); - ISTANBUL - } - SpecId::MUIR_GLACIER => { - gas_opcodee!(MUIRGLACIER, SpecId::MUIR_GLACIER); - MUIRGLACIER - } - SpecId::BERLIN => { - gas_opcodee!(BERLIN, SpecId::BERLIN); - BERLIN - } - SpecId::LONDON => { - gas_opcodee!(LONDON, SpecId::LONDON); - LONDON - } - SpecId::ARROW_GLACIER => { - gas_opcodee!(ARROW_GLACIER, SpecId::ARROW_GLACIER); - ARROW_GLACIER - } - SpecId::GRAY_GLACIER => { - gas_opcodee!(GRAY_GLACIER, SpecId::GRAY_GLACIER); - GRAY_GLACIER - } - SpecId::MERGE => { - gas_opcodee!(MERGE, SpecId::MERGE); - MERGE - } - SpecId::SHANGHAI => { - gas_opcodee!(SHANGHAI, SpecId::SHANGHAI); - SHANGHAI - } - SpecId::CANCUN => { - gas_opcodee!(CANCUN, SpecId::CANCUN); - CANCUN - } - SpecId::LATEST => { - gas_opcodee!(LATEST, SpecId::LATEST); - LATEST - } - } -} - pub const OPCODE_JUMPMAP: [Option<&'static str>; 256] = [ /* 0x00 */ Some("STOP"), /* 0x01 */ Some("ADD"), diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index fee9dc2231..34b4c3f03d 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -1,10 +1,11 @@ +use crate::gas; use crate::InstructionResult; use revm_primitives::{Spec, SpecId::SHANGHAI, U256}; use crate::{interpreter::Interpreter, Host}; pub fn pop(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); if let Some(ret) = interpreter.stack.reduce_one() { interpreter.instruction_result = ret; } @@ -13,16 +14,16 @@ pub fn pop(interpreter: &mut Interpreter, _host: &mut dyn Host) { /// EIP-3855: PUSH0 instruction /// Introduce a new instruction which pushes the constant value 0 onto the stack pub fn push0(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); // EIP-3855: PUSH0 instruction check!(interpreter, SPEC::enabled(SHANGHAI)); + gas!(interpreter, gas::BASE); if let Err(result) = interpreter.stack.push(U256::ZERO) { interpreter.instruction_result = result; } } pub fn push(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); let start = interpreter.instruction_pointer; // Safety: In Analysis we appended needed bytes for bytecode so that we are safe to just add without // checking if it is out of bound. This makes both of our unsafes block safe to do. @@ -37,14 +38,14 @@ pub fn push(interpreter: &mut Interpreter, _host: &mut dyn Host) } pub fn dup(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); if let Some(ret) = interpreter.stack.dup::() { interpreter.instruction_result = ret; } } pub fn swap(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); if let Some(ret) = interpreter.stack.swap::() { interpreter.instruction_result = ret; } diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 4659636236..bfef1465f7 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -22,17 +22,17 @@ pub fn sha3(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn address(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push_b256!(interpreter, B256::from(interpreter.contract.address)); } pub fn caller(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push_b256!(interpreter, B256::from(interpreter.contract.caller)); } pub fn codesize(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, U256::from(interpreter.contract.bytecode.len())); } @@ -61,7 +61,7 @@ pub fn codecopy(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn calldataload(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::VERYLOW); + gas!(interpreter, gas::VERYLOW); pop!(interpreter, index); let index = as_usize_saturated!(index); @@ -78,12 +78,12 @@ pub fn calldataload(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn calldatasize(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, U256::from(interpreter.contract.input.len())); } pub fn callvalue(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, interpreter.contract.value); } @@ -109,7 +109,7 @@ pub fn calldatacopy(interpreter: &mut Interpreter, _host: &mut dyn Host) { } pub fn returndatasize(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY check!(interpreter, SPEC::enabled(BYZANTIUM)); push!( @@ -145,9 +145,6 @@ pub fn returndatacopy(interpreter: &mut Interpreter, _host: &mut dyn } pub fn gas(interpreter: &mut Interpreter, _host: &mut dyn Host) { - // gas!(interp, gas::BASE); + gas!(interpreter, gas::BASE); push!(interpreter, U256::from(interpreter.gas.remaining())); - if let Some(ret) = interpreter.add_next_gas_block(interpreter.program_counter() - 1) { - interpreter.instruction_result = ret; - } } diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index ddf7cf78df..d9ab106b57 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -11,7 +11,7 @@ pub use stack::Stack; use crate::primitives::{Bytes, Spec}; use crate::{ instructions::{eval, InstructionResult}, - Gas, Host, USE_GAS, + Gas, Host, }; use core::ops::Range; @@ -116,17 +116,6 @@ impl Interpreter { &self.stack } - #[inline(always)] - pub fn add_next_gas_block(&mut self, pc: usize) -> Option { - if USE_GAS { - let gas_block = self.contract.gas_block(pc); - if !self.gas.record_cost(gas_block) { - return Some(InstructionResult::OutOfGas); - } - } - None - } - /// Return a reference of the program counter. pub fn program_counter(&self) -> usize { // Safety: this is just subtraction of pointers, it is safe to do. @@ -150,10 +139,6 @@ impl Interpreter { /// loop steps until we are finished with execution pub fn run(&mut self, host: &mut H) -> InstructionResult { - // add first gas_block - if USE_GAS && !self.gas.record_cost(self.contract.first_gas_block()) { - return InstructionResult::OutOfGas; - } while self.instruction_result == InstructionResult::Continue { self.step::(host) } @@ -162,10 +147,6 @@ impl Interpreter { /// loop steps until we are finished with execution pub fn run_inspect(&mut self, host: &mut H) -> InstructionResult { - // add first gas_block - if USE_GAS && !self.gas.record_cost(self.contract.first_gas_block()) { - return InstructionResult::OutOfGas; - } while self.instruction_result == InstructionResult::Continue { // step let ret = host.step(self, self.is_static); diff --git a/crates/interpreter/src/interpreter/analysis.rs b/crates/interpreter/src/interpreter/analysis.rs index 0bd70d2a01..e52f7c6d7e 100644 --- a/crates/interpreter/src/interpreter/analysis.rs +++ b/crates/interpreter/src/interpreter/analysis.rs @@ -1,10 +1,15 @@ -use crate::primitives::{ - AnalysisData, Bytecode, BytecodeState, Bytes, Spec, ValidJumpAddress, B256, -}; -use crate::{opcode, spec_opcode_gas}; +use crate::opcode; +use crate::primitives::{Bytecode, BytecodeState, Bytes, B256}; use alloc::sync::Arc; - -pub fn to_analysed(bytecode: Bytecode) -> Bytecode { +use bitvec::prelude::bitvec; +use revm_primitives::JumpMap; + +/// Perform bytecode analysis. +/// +/// The analysis finds and caches valid jump destinations for later execution as an optimization step. +/// +/// If the bytecode is already analyzed, it is returned as-is. +pub fn to_analysed(bytecode: Bytecode) -> Bytecode { let hash = bytecode.hash; let (bytecode, len) = match bytecode.state { BytecodeState::Raw => { @@ -15,81 +20,42 @@ pub fn to_analysed(bytecode: Bytecode) -> Bytecode { BytecodeState::Checked { len } => (bytecode.bytecode, len), _ => return bytecode, }; - let jumptable = analyze::(bytecode.as_ref()); + let jump_map = analyze(bytecode.as_ref()); Bytecode { bytecode, hash, - state: BytecodeState::Analysed { len, jumptable }, + state: BytecodeState::Analysed { len, jump_map }, } } -/// Analyze bytecode to get jumptable and gas blocks. -fn analyze(code: &[u8]) -> ValidJumpAddress { - let opcode_gas = spec_opcode_gas(SPEC::SPEC_ID); - - let mut analysis = ValidJumpAddress { - first_gas_block: 0, - analysis: Arc::new(vec![AnalysisData::none(); code.len()]), - }; - let jumps = Arc::get_mut(&mut analysis.analysis).unwrap(); - - let mut index = 0; - let mut gas_in_block: u32 = 0; - let mut block_start: usize = 0; - - // first gas block - while index < code.len() { - let opcode = *code.get(index).unwrap(); - let info = opcode_gas.get(opcode as usize).unwrap(); - analysis.first_gas_block += info.get_gas(); - - index += if info.is_push() { - ((opcode - opcode::PUSH1) + 2) as usize +/// Analyzs bytecode to build a jump map. +fn analyze(code: &[u8]) -> JumpMap { + let mut jumps = bitvec![0; code.len()]; + + let range = code.as_ptr_range(); + let start = range.start; + let mut iterator = start; + let end = range.end; + while iterator < end { + let opcode = unsafe { *iterator }; + if opcode::JUMPDEST == opcode { + // SAFETY: jumps are max length of the code + unsafe { jumps.set_unchecked(iterator.offset_from(start) as usize, true) } + iterator = unsafe { iterator.offset(1) }; } else { - 1 - }; - - if info.is_gas_block_end() { - block_start = index - 1; - if info.is_jump() { - jumps.get_mut(block_start).unwrap().set_is_jump(); + let push_offset = opcode.wrapping_sub(opcode::PUSH1); + if push_offset < 32 { + // SAFETY: iterator access range is checked in the while loop + iterator = unsafe { iterator.offset((push_offset + 2) as isize) }; + } else { + // SAFETY: iterator access range is checked in the while loop + iterator = unsafe { iterator.offset(1) }; } - break; } } - while index < code.len() { - let opcode = *code.get(index).unwrap(); - let info = opcode_gas.get(opcode as usize).unwrap(); - gas_in_block += info.get_gas(); - - if info.is_gas_block_end() { - if info.is_jump() { - jumps.get_mut(index).unwrap().set_is_jump(); - } - jumps - .get_mut(block_start) - .unwrap() - .set_gas_block(gas_in_block); - block_start = index; - gas_in_block = 0; - index += 1; - } else { - index += if info.is_push() { - ((opcode - opcode::PUSH1) + 2) as usize - } else { - 1 - }; - } - } - if gas_in_block != 0 { - jumps - .get_mut(block_start) - .unwrap() - .set_gas_block(gas_in_block); - } - analysis + JumpMap(Arc::new(jumps)) } #[derive(Clone)] @@ -97,7 +63,7 @@ pub struct BytecodeLocked { bytecode: Bytes, len: usize, hash: B256, - jumptable: ValidJumpAddress, + jump_map: JumpMap, } impl Default for BytecodeLocked { @@ -112,12 +78,12 @@ impl TryFrom for BytecodeLocked { type Error = (); fn try_from(bytecode: Bytecode) -> Result { - if let BytecodeState::Analysed { len, jumptable } = bytecode.state { + if let BytecodeState::Analysed { len, jump_map } = bytecode.state { Ok(BytecodeLocked { bytecode: bytecode.bytecode, len, hash: bytecode.hash, - jumptable, + jump_map, }) } else { Err(()) @@ -147,7 +113,7 @@ impl BytecodeLocked { hash: self.hash, state: BytecodeState::Analysed { len: self.len, - jumptable: self.jumptable, + jump_map: self.jump_map, }, } } @@ -159,7 +125,7 @@ impl BytecodeLocked { &self.bytecode.as_ref()[..self.len] } - pub fn jumptable(&self) -> &ValidJumpAddress { - &self.jumptable + pub fn jump_map(&self) -> &JumpMap { + &self.jump_map } } diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index c8fc7286e4..a8ce90b180 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,5 +1,5 @@ use super::analysis::{to_analysed, BytecodeLocked}; -use crate::primitives::{Bytecode, Bytes, Spec, B160, U256}; +use crate::primitives::{Bytecode, Bytes, B160, U256}; use crate::CallContext; use revm_primitives::{Env, TransactTo}; @@ -61,16 +61,8 @@ impl AnalysisData { } impl Contract { - pub fn new( - input: Bytes, - bytecode: Bytecode, - address: B160, - caller: B160, - value: U256, - ) -> Self { - let bytecode = to_analysed::(bytecode) - .try_into() - .expect("it is analyzed"); + pub fn new(input: Bytes, bytecode: Bytecode, address: B160, caller: B160, value: U256) -> Self { + let bytecode = to_analysed(bytecode).try_into().expect("it is analyzed"); Self { input, @@ -82,13 +74,12 @@ impl Contract { } /// Create new contract from environment - /// TODO: Add spec related match to analyze bytecode by env.cfg.spec_id variable - pub fn new_env(env: &Env, bytecode: Bytecode) -> Self { + pub fn new_env(env: &Env, bytecode: Bytecode) -> Self { let contract_address = match env.tx.transact_to { TransactTo::Call(caller) => caller, TransactTo::Create(..) => B160::zero(), }; - Self::new::( + Self::new( env.tx.data.clone(), bytecode, contract_address, @@ -98,22 +89,11 @@ impl Contract { } pub fn is_valid_jump(&self, possition: usize) -> bool { - self.bytecode.jumptable().is_valid(possition) + self.bytecode.jump_map().is_valid(possition) } - pub fn gas_block(&self, possition: usize) -> u64 { - self.bytecode.jumptable().gas_block(possition) - } - pub fn first_gas_block(&self) -> u64 { - self.bytecode.jumptable().first_gas_block as u64 - } - - pub fn new_with_context( - input: Bytes, - bytecode: Bytecode, - call_context: &CallContext, - ) -> Self { - Self::new::( + pub fn new_with_context(input: Bytes, bytecode: Bytecode, call_context: &CallContext) -> Self { + Self::new( input, bytecode, call_context.address, diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 5471acbcfa..0976c3875a 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -17,7 +17,7 @@ pub use gas::Gas; pub use host::{DummyHost, Host}; pub use inner_models::*; pub use instruction_result::InstructionResult; -pub use instructions::opcode::{self, spec_opcode_gas, OpCode, OPCODE_JUMPMAP}; +pub use instructions::opcode::{self, OpCode, OPCODE_JUMPMAP}; pub use interpreter::*; pub use interpreter::{BytecodeLocked, Contract, Interpreter, Memory, Stack}; diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index e5aa98aa98..6e09d03195 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -17,6 +17,7 @@ primitive-types = { version = "0.12", default-features = false } rlp = { version = "0.5", default-features = false } # used for create2 address calculation ruint = { version = "1.7.0", features = ["primitive-types", "rlp"] } auto_impl = "1.0" +bitvec = { version = "1", default-features = false } # bits B256 B160 crate fixed-hash = { version = "0.8", default-features = false, features = [ @@ -63,13 +64,14 @@ optional_balance_check = [] optional_block_gas_limit = [] optional_eip3607 = [] optional_gas_refund = [] -std = ["bytes/std", "rlp/std", "hex/std"] +std = ["bytes/std", "rlp/std", "hex/std", "bitvec/std"] serde = [ "dep:serde", "hex/serde", "hashbrown/serde", "ruint/serde", "bytes/serde", + "bitvec/serde", ] arbitrary = [ "ruint/arbitrary", diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index 7c4d2500a8..334c5f1cd7 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -1,21 +1,27 @@ -mod jump_table; - use crate::{keccak256, B256, KECCAK_EMPTY}; use alloc::{sync::Arc, vec, vec::Vec}; +use bitvec::prelude::{bitvec, Lsb0}; +use bitvec::vec::BitVec; use bytes::Bytes; -pub use jump_table::{Analysis, AnalysisData, ValidJumpAddress}; + +/// A map of valid `jump` destinations. +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct JumpMap(pub Arc); + +impl JumpMap { + /// Check if `pc` is a valid jump destination. + pub fn is_valid(&self, pc: usize) -> bool { + pc < self.0.len() && self.0[pc] + } +} #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum BytecodeState { Raw, - Checked { - len: usize, - }, - Analysed { - len: usize, - jumptable: ValidJumpAddress, - }, + Checked { len: usize }, + Analysed { len: usize, jump_map: JumpMap }, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -41,7 +47,7 @@ impl Bytecode { hash: KECCAK_EMPTY, state: BytecodeState::Analysed { len: 0, - jumptable: ValidJumpAddress::new(Arc::new(vec![AnalysisData::none()]), 0), + jump_map: JumpMap(Arc::new(bitvec![0])), }, } } diff --git a/crates/primitives/src/bytecode/jump_table.rs b/crates/primitives/src/bytecode/jump_table.rs deleted file mode 100644 index 89782c36e0..0000000000 --- a/crates/primitives/src/bytecode/jump_table.rs +++ /dev/null @@ -1,87 +0,0 @@ -use alloc::{sync::Arc, vec::Vec}; - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Analysis { - JumpDest, - GasBlockEnd, //contains gas for next block - None, -} - -const JUMP_MASK: u32 = 0x80000000; - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct AnalysisData { - /// This variable packs two informations: - /// IS_JUMP (1bit) | gas block ( 31bits) - is_jump_and_gas_block: u32, -} - -impl AnalysisData { - pub fn none() -> Self { - AnalysisData { - is_jump_and_gas_block: 0, - } - } - - pub fn set_is_jump(&mut self) { - self.is_jump_and_gas_block |= JUMP_MASK; - } - - pub fn set_gas_block(&mut self, gas_block: u32) { - let jump = self.is_jump_and_gas_block & JUMP_MASK; - self.is_jump_and_gas_block = gas_block | jump; - } - - pub fn is_jump(&self) -> bool { - self.is_jump_and_gas_block & JUMP_MASK == JUMP_MASK - } - - pub fn gas_block(&self) -> u64 { - (self.is_jump_and_gas_block & (!JUMP_MASK)) as u64 - } -} - -/// Mapping of valid jump destination from code. -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ValidJumpAddress { - pub first_gas_block: u32, - /// Rc is used here so that we dont need to copy vector. We can move it to more suitable more accessable structure - /// without copying underlying vec. - pub analysis: Arc>, -} - -impl ValidJumpAddress { - pub fn new(analysis: Arc>, first_gas_block: u32) -> Self { - Self { - analysis, - first_gas_block, - } - } - /// Get the length of the valid mapping. This is the same as the - /// code bytes. - - pub fn len(&self) -> usize { - self.analysis.len() - } - - /// Returns true if the valid list is empty - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns `true` if the position is a valid jump destination. If - /// not, returns `false`. - pub fn is_valid(&self, position: usize) -> bool { - if position >= self.analysis.len() { - return false; - } - self.analysis[position].is_jump() - } - - pub fn gas_block(&self, position: usize) -> u64 { - self.analysis[position].gas_block() - } -} diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 99e81a8b3b..bd198fcfd0 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -585,7 +585,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } // Create new interpreter and execute initcode - let contract = Contract::new::( + let contract = Contract::new( Bytes::new(), Bytecode::new_raw(inputs.init_code.clone()), created_address, @@ -678,7 +678,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, let bytecode = match self.data.env.cfg.perf_analyse_created_bytecodes { AnalysisKind::Raw => Bytecode::new_raw(bytes.clone()), AnalysisKind::Check => Bytecode::new_raw(bytes.clone()).to_checked(), - AnalysisKind::Analyse => to_analysed::(Bytecode::new_raw(bytes.clone())), + AnalysisKind::Analyse => to_analysed(Bytecode::new_raw(bytes.clone())), }; self.data @@ -819,11 +819,8 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } } else { // Create interpreter and execute subcall - let contract = Contract::new_with_context::( - inputs.input.clone(), - bytecode, - &inputs.context, - ); + let contract = + Contract::new_with_context(inputs.input.clone(), bytecode, &inputs.context); #[cfg(feature = "memory_limit")] let mut interpreter = Interpreter::new_with_memory_limit( diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index fa739aef78..df3d5055d5 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -7,13 +7,6 @@ use crate::{evm_impl::EVMData, Inspector}; #[allow(dead_code)] #[derive(Clone, Copy, Debug, Default)] pub struct GasInspector { - /// We now batch continual gas_block in one go, that means we need to reduce it if we want - /// to get correct gas remaining. Check revm/interpreter/contract/analyze for more information - reduced_gas_block: u64, - full_gas_block: u64, - was_return: bool, - was_jumpi: Option, - gas_remaining: u64, last_gas_cost: u64, } @@ -36,7 +29,6 @@ impl Inspector for GasInspector { _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> InstructionResult { - self.full_gas_block = interp.contract.first_gas_block(); self.gas_remaining = interp.gas.limit(); InstructionResult::Continue } @@ -47,27 +39,10 @@ impl Inspector for GasInspector { #[cfg(not(feature = "no_gas_measuring"))] fn step( &mut self, - interp: &mut crate::interpreter::Interpreter, - data: &mut EVMData<'_, DB>, + _interp: &mut crate::interpreter::Interpreter, + _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> InstructionResult { - let op = interp.current_opcode(); - - // calculate gas_block - let infos = crate::interpreter::spec_opcode_gas(data.env.cfg.spec_id); - let info = &infos[op as usize]; - - let pc = interp.program_counter(); - if op == crate::interpreter::opcode::JUMPI { - self.reduced_gas_block += info.get_gas() as u64; - self.was_jumpi = Some(pc); - } else if info.is_gas_block_end() { - self.reduced_gas_block = 0; - self.full_gas_block = interp.contract.gas_block(pc); - } else { - self.reduced_gas_block += info.get_gas() as u64; - } - InstructionResult::Continue } @@ -79,26 +54,8 @@ impl Inspector for GasInspector { _is_static: bool, _eval: InstructionResult, ) -> InstructionResult { - let pc = interp.program_counter(); - if let Some(was_pc) = self.was_jumpi { - if let Some(new_pc) = pc.checked_sub(1) { - if was_pc == new_pc { - self.reduced_gas_block = 0; - self.full_gas_block = interp.contract.gas_block(was_pc); - } - } - self.was_jumpi = None; - } else if self.was_return { - // we are ok to decrement PC by one as it is return of call - let previous_pc = pc - 1; - self.reduced_gas_block = 0; - self.full_gas_block = interp.contract.gas_block(previous_pc); - self.was_return = false; - } - let last_gas = self.gas_remaining; - self.gas_remaining = - interp.gas.remaining() + (self.full_gas_block - self.reduced_gas_block); + self.gas_remaining = interp.gas.remaining(); if last_gas > self.gas_remaining { self.last_gas_cost = last_gas - self.gas_remaining; } else { @@ -116,7 +73,6 @@ impl Inspector for GasInspector { out: Bytes, _is_static: bool, ) -> (InstructionResult, Gas, Bytes) { - self.was_return = true; (ret, remaining_gas, out) } @@ -129,7 +85,6 @@ impl Inspector for GasInspector { remaining_gas: Gas, out: Bytes, ) -> (InstructionResult, Option, Gas, Bytes) { - self.was_return = true; (ret, address, remaining_gas, out) } }