Skip to content

Commit

Permalink
refactor: remove gas blocks (#391)
Browse files Browse the repository at this point in the history
* refactor: remove gas blocks

* chore: fmt

* chore: clean up gas inspector

* refactor: smol cleanup

* feat: use a bitvec as jumpmap

* chore: fmt

* Make analysis faster

* Update crates/interpreter/src/instructions/stack.rs

* nits
  • Loading branch information
onbjerg committed Mar 1, 2023
1 parent 8dc024a commit f91d5f9
Show file tree
Hide file tree
Showing 24 changed files with 181 additions and 819 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions bins/revm-test/src/bin/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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::<LondonSpec>(Bytecode::new_raw(contract_data));
let bytecode_analysed = to_analysed(Bytecode::new_raw(contract_data));

evm.database(BenchmarkDB::new_bytecode(bytecode_raw));

Expand Down
2 changes: 1 addition & 1 deletion bins/revm-test/src/bin/snailtracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<BerlinSpec>(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..
Expand Down
12 changes: 6 additions & 6 deletions bins/revme/src/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion crates/interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down
13 changes: 9 additions & 4 deletions crates/interpreter/src/gas/calc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,16 @@ pub fn extcodecopy_cost<SPEC: Spec>(len: u64, is_cold: bool) -> Option<u64> {
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 })?)
}
Expand Down
10 changes: 10 additions & 0 deletions crates/interpreter/src/instructions/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,57 @@ 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)
};
}

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)
}
Expand All @@ -74,6 +83,7 @@ pub fn eval_exp<SPEC: Spec>(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
Expand Down
15 changes: 15 additions & 0 deletions crates/interpreter/src/instructions/bitwise.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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;

Expand All @@ -98,20 +110,23 @@ pub fn byte(interpreter: &mut Interpreter, _host: &mut dyn Host) {
pub fn shl<SPEC: Spec>(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);
}

pub fn shr<SPEC: Spec>(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);
}

pub fn sar<SPEC: Spec>(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::<true>(op2);
Expand Down
12 changes: 3 additions & 9 deletions crates/interpreter/src/instructions/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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));
}

Expand Down
Loading

0 comments on commit f91d5f9

Please sign in to comment.