Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Loop call stack #851

Merged
merged 14 commits into from
Nov 7, 2023
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ default-members = ["crates/revm"]
[profile.release]
lto = true
codegen-units = 1
debug = true

[profile.ethtests]
inherits = "test"
Expand Down
1 change: 0 additions & 1 deletion bins/revme/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ revm = { path = "../../crates/revm", version = "3.5.0", default-features = false
alloy-rlp = { version = "0.3", default-features = false, features = [
"arrayvec",
] }
ruint = { version = "1.9.0", features = ["rlp", "serde"] }
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
structopt = "0.3"
Expand Down
12 changes: 3 additions & 9 deletions bins/revme/src/cmd/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,18 @@ fn skip_test(path: &Path) -> bool {
// txbyte is of type 02 and we dont parse tx bytes for this test to fail.
| "typeTwoBerlin.json"

// Test checks if nonce overflows. We are handling this correctly but we are not parsing
// exception in testsuite There are more nonce overflow tests that are in internal
// call/create, and those tests are passing and are enabled.
| "CreateTransactionHighNonce.json"

// Need to handle Test errors
| "transactionIntinsicBug.json"

// Test check if gas price overflows, we handle this correctly but does not match tests specific exception.
| "HighGasPrice.json"
| "CREATE_HighNonce.json"
| "CREATE_HighNonceMinus1.json"
| "CreateTransactionHighNonce.json"

// Skip test where basefee/accesslist/difficulty is present but it shouldn't be supported in
// London/Berlin/TheMerge. https://github.com/ethereum/tests/blob/5b7e1ab3ffaf026d99d20b17bb30f533a2c80c8b/GeneralStateTests/stExample/eip1559.json#L130
// It is expected to not execute these tests.
| "accessListExample.json"
| "basefeeExample.json"
| "eip1559.json"
| "mergeTest.json"
Expand All @@ -98,7 +93,6 @@ fn skip_test(path: &Path) -> bool {
| "static_Call50000_sha256.json"
| "loopMul.json"
| "CALLBlake2f_MaxRounds.json"
| "shiftCombinations.json"
) || path_str.contains("stEOF")
}

Expand Down Expand Up @@ -349,8 +343,6 @@ pub fn execute_test_suite(
evm.database(&mut state);

let path = path.display();
println!("Test {name:?} (index: {index}, path: {path}) failed:\n{e}");

println!("\nTraces:");
let _ = evm.inspect_commit(TracerEip3155::new(Box::new(stdout()), false, false));

Expand All @@ -359,6 +351,8 @@ pub fn execute_test_suite(
println!("\nState before: {cache_state:#?}");
println!("\nState after: {:#?}", evm.db().unwrap().cache);
println!("\nEnvironment: {env:#?}");
println!("\nTest name: {name:?} (index: {index}, path: {path}) failed:\n{e}");

return Err(e);
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ dev = [
"optional_no_base_fee",
]
memory_limit = ["revm-primitives/memory_limit"]
no_gas_measuring = ["revm-primitives/no_gas_measuring"]
optional_balance_check = ["revm-primitives/optional_balance_check"]
optional_block_gas_limit = ["revm-primitives/optional_block_gas_limit"]
optional_eip3607 = ["revm-primitives/optional_eip3607"]
Expand Down
3 changes: 0 additions & 3 deletions crates/interpreter/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ impl Gas {
/// Records an explicit cost.
///
/// Returns `false` if the gas limit is exceeded.
///
/// This function is called on every instruction in the interpreter if the feature
/// `no_gas_measuring` is not enabled.
#[inline(always)]
pub fn record_cost(&mut self, cost: u64) -> bool {
let all_used_gas = self.all_used_gas.saturating_add(cost);
Expand Down
4 changes: 1 addition & 3 deletions crates/interpreter/src/gas/calc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,12 @@ pub fn selfdestruct_cost<SPEC: Spec>(res: SelfDestructResult) -> u64 {
}

pub fn call_cost<SPEC: Spec>(
value: U256,
transfers_value: bool,
is_new: bool,
is_cold: bool,
is_call_or_callcode: bool,
is_call_or_staticcall: bool,
) -> u64 {
let transfers_value = value != U256::default();

let call_gas = if SPEC::enabled(BERLIN) {
if is_cold {
COLD_ACCOUNT_ACCESS_COST
Expand Down
16 changes: 1 addition & 15 deletions crates/interpreter/src/host.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::primitives::Bytecode;
use crate::{
primitives::{Address, Bytes, Env, B256, U256},
CallInputs, CreateInputs, Gas, InstructionResult, SelfDestructResult, SharedMemory,
SelfDestructResult,
};
use alloc::vec::Vec;
pub use dummy::DummyHost;
Expand Down Expand Up @@ -52,20 +52,6 @@ pub trait Host {
/// Emit a log owned by `address` with given `topics` and `data`.
fn log(&mut self, address: Address, topics: Vec<B256>, data: Bytes);

/// Invoke a call operation.
fn call(
&mut self,
input: &mut CallInputs,
shared_memory: &mut SharedMemory,
) -> (InstructionResult, Gas, Bytes);

/// Invoke a create operation.
fn create(
&mut self,
inputs: &mut CreateInputs,
shared_memory: &mut SharedMemory,
) -> (InstructionResult, Option<Address>, Gas, Bytes);

/// Mark `address` to be deleted, with funds transferred to `target`.
fn selfdestruct(&mut self, address: Address, target: Address) -> Option<SelfDestructResult>;
}
20 changes: 1 addition & 19 deletions crates/interpreter/src/host/dummy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::primitives::{hash_map::Entry, Bytecode, Bytes, HashMap, U256};
use crate::{
primitives::{Address, Env, Log, B256, KECCAK_EMPTY},
CallInputs, CreateInputs, Gas, Host, InstructionResult, SelfDestructResult, SharedMemory,
Host, SelfDestructResult,
};
use alloc::vec::Vec;

Expand Down Expand Up @@ -118,22 +118,4 @@ impl Host for DummyHost {
fn selfdestruct(&mut self, _address: Address, _target: Address) -> Option<SelfDestructResult> {
panic!("Selfdestruct is not supported for this host")
}

#[inline]
fn create(
&mut self,
_inputs: &mut CreateInputs,
_shared_memory: &mut SharedMemory,
) -> (InstructionResult, Option<Address>, Gas, Bytes) {
panic!("Create is not supported for this host")
}

#[inline]
fn call(
&mut self,
_input: &mut CallInputs,
_shared_memory: &mut SharedMemory,
) -> (InstructionResult, Gas, Bytes) {
panic!("Call is not supported for this host")
}
}
20 changes: 13 additions & 7 deletions crates/interpreter/src/instruction_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ use crate::primitives::{Eval, Halt};
pub enum InstructionResult {
// success codes
Continue = 0x00,
Stop = 0x01,
Return = 0x02,
SelfDestruct = 0x03,
Stop,
Return,
SelfDestruct,

// revert codes
Revert = 0x20, // revert opcode
CallTooDeep = 0x21,
OutOfFund = 0x22,
Revert = 0x10, // revert opcode
CallTooDeep,
OutOfFund,

// Actions
CallOrCreate = 0x20,

// error codes
OutOfGas = 0x50,
Expand Down Expand Up @@ -95,8 +98,10 @@ pub enum SuccessOrHalt {
Revert,
Halt(Halt),
FatalExternalError,
// this is internal opcode.
/// Internal instruction that signals Interpreter should continue running.
InternalContinue,
/// Internal instruction that signals subcall.
InternalCallOrCreate,
}

impl SuccessOrHalt {
Expand Down Expand Up @@ -145,6 +150,7 @@ impl From<InstructionResult> for SuccessOrHalt {
InstructionResult::Return => Self::Success(Eval::Return),
InstructionResult::SelfDestruct => Self::Success(Eval::SelfDestruct),
InstructionResult::Revert => Self::Revert,
InstructionResult::CallOrCreate => Self::InternalCallOrCreate, // used only in interpreter loop
InstructionResult::CallTooDeep => Self::Halt(Halt::CallTooDeep), // not gonna happen for first call
InstructionResult::OutOfFund => Self::Halt(Halt::OutOfFund), // Check for first call is done separately.
InstructionResult::OutOfGas => Self::Halt(Halt::OutOfGas(
Expand Down
2 changes: 1 addition & 1 deletion crates/interpreter/src/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! EVM opcode implementations.

#[macro_use]
mod macros;
pub mod macros;

pub mod arithmetic;
pub mod bitwise;
Expand Down
22 changes: 11 additions & 11 deletions crates/interpreter/src/instructions/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,67 @@ use crate::{
Host, InstructionResult, Interpreter,
};

pub fn wrapped_add<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn wrapped_add<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1.wrapping_add(*op2);
}

pub fn wrapping_mul<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn wrapping_mul<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
*op2 = op1.wrapping_mul(*op2);
}

pub fn wrapping_sub<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn wrapping_sub<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1.wrapping_sub(*op2);
}

pub fn div<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn div<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if *op2 != U256::ZERO {
*op2 = op1.wrapping_div(*op2);
}
}

pub fn sdiv<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn sdiv<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
*op2 = i256_div(op1, *op2);
}

pub fn rem<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn rem<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if *op2 != U256::ZERO {
*op2 = op1.wrapping_rem(*op2);
}
}

pub fn smod<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn smod<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if *op2 != U256::ZERO {
*op2 = i256_mod(op1, *op2)
}
}

pub fn addmod<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn addmod<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::MID);
pop_top!(interpreter, op1, op2, op3);
*op3 = op1.add_mod(op2, *op3)
}

pub fn mulmod<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn mulmod<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::MID);
pop_top!(interpreter, op1, op2, op3);
*op3 = op1.mul_mod(op2, *op3)
}

pub fn exp<H: Host, SPEC: Spec>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn exp<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pop_top!(interpreter, op1, op2);
gas_or_fail!(interpreter, gas::exp_cost::<SPEC>(*op2));
*op2 = op1.pow(*op2);
Expand All @@ -86,7 +86,7 @@ pub fn exp<H: Host, SPEC: Spec>(interpreter: &mut Interpreter<'_>, _host: &mut H
/// `y | !mask` where `|` is the bitwise `OR` and `!` is bitwise negation. Similarly, if
/// `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<H: Host>(interpreter: &mut Interpreter<'_>, _host: &mut H) {
pub fn signextend<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if op1 < U256::from(32) {
Expand Down
Loading