Skip to content

Commit

Permalink
EIP-7702 basic implementation, CI and tests changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mrLSD committed Aug 27, 2024
1 parent 3c4c1c1 commit 226d7eb
Show file tree
Hide file tree
Showing 36 changed files with 643 additions and 308 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ jobs:
run: |
cargo run -r -p evm-jsontests -F enable-slow-tests -- state -f \
ethtests/GeneralStateTests/ \
ethtests/LegacyTests/Cancun/GeneralStateTests/ \
ethtests/EIPTests/StateTests/
ethtests/LegacyTests/Cancun/GeneralStateTests/
# Temporally disable as EOFv1 not implemented
# ethtests/EIPTests/StateTests/
- name: Run Ethereum vm tests
run: |
Expand Down Expand Up @@ -134,8 +135,9 @@ jobs:
export PATH="$PATH:$HOME/.cargo/bin"
cargo run -r -p evm-jsontests -F enable-slow-tests -- state -f \
ethtests/GeneralStateTests/ \
ethtests/LegacyTests/Cancun/GeneralStateTests/ \
ethtests/EIPTests/StateTests/
ethtests/LegacyTests/Cancun/GeneralStateTests/
# Temporally disable as EOFv1 not implemented
# ethtests/EIPTests/StateTests/
cargo run -r -p evm-jsontests -F enable-slow-tests -- vm -f \
ethtests/LegacyTests/Constantinople/VMTests/vmArithmeticTest \
ethtests/LegacyTests/Constantinople/VMTests/vmBitwiseLogicOperation \
Expand Down
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ keywords.workspace = true
edition.workspace = true

[workspace.dependencies]
evm = { version = "0.44.1", path = "." }
evm-core = { version = "0.44.1", path = "core", default-features = false }
evm-gasometer = { version = "0.44.1", path = "gasometer", default-features = false }
evm-runtime = { version = "0.44.1", path = "runtime", default-features = false }
evm = { version = "0.45.2", path = "." }
evm-core = { version = "0.45.2", path = "core", default-features = false }
evm-gasometer = { version = "0.45.2", path = "gasometer", default-features = false }
evm-runtime = { version = "0.45.2", path = "runtime", default-features = false }
primitive-types = { version = "0.12", default-features = false }
auto_impl = "1.0"
sha3 = { version = "0.10", default-features = false }
Expand Down Expand Up @@ -87,7 +87,7 @@ create-fixed = []
print-debug = ["evm-gasometer/print-debug"]

[workspace.package]
version = "0.44.1"
version = "0.45.2"
license = "Apache-2.0"
authors = ["Aurora Labs <[email protected]>", "Wei Tang <[email protected]>", "Parity Technologies <[email protected]>"]
description = "Portable Ethereum Virtual Machine implementation written in pure Rust."
Expand Down
15 changes: 8 additions & 7 deletions benches/loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ fn run_loop_contract() {
effective_gas_price: U256::zero(),
origin: H160::default(),
block_hashes: Vec::new(),
block_number: Default::default(),
block_coinbase: Default::default(),
block_timestamp: Default::default(),
block_difficulty: Default::default(),
block_gas_limit: Default::default(),
block_number: U256::default(),
block_coinbase: H160::default(),
block_timestamp: U256::default(),
block_difficulty: U256::default(),
block_gas_limit: U256::default(),
chain_id: U256::one(),
block_base_fee_per_gas: U256::zero(),
block_randomness: None,
Expand All @@ -30,7 +30,7 @@ fn run_loop_contract() {
H160::from_str("0x1000000000000000000000000000000000000000").unwrap(),
MemoryAccount {
nonce: U256::one(),
balance: U256::from(10000000),
balance: U256::from(10_000_000),
storage: BTreeMap::new(),
code: hex::decode("6080604052348015600f57600080fd5b506004361060285760003560e01c80630f14a40614602d575b600080fd5b605660048036036020811015604157600080fd5b8101908080359060200190929190505050606c565b6040518082815260200191505060405180910390f35b6000806000905060005b83811015608f5760018201915080806001019150506076565b508091505091905056fea26469706673582212202bc9ec597249a9700278fe4ce78da83273cb236e76d4d6797b441454784f901d64736f6c63430007040033").unwrap(),
},
Expand All @@ -39,7 +39,7 @@ fn run_loop_contract() {
H160::from_str("0xf000000000000000000000000000000000000000").unwrap(),
MemoryAccount {
nonce: U256::one(),
balance: U256::from(10000000),
balance: U256::from(10_000_000),
storage: BTreeMap::new(),
code: Vec::new(),
},
Expand All @@ -60,6 +60,7 @@ fn run_loop_contract() {
// hex::decode("0f14a4060000000000000000000000000000000000000000000000000000000000002ee0").unwrap(),
u64::MAX,
Vec::new(),
&[],
);
}

Expand Down
4 changes: 3 additions & 1 deletion core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,15 @@ pub enum ExitError {
Other(Cow<'static, str>),

/// Nonce reached maximum value of 2^64-1
/// https://eips.ethereum.org/EIPS/eip-2681
/// <https://eips.ethereum.org/EIPS/eip-2681>
#[cfg_attr(feature = "with-codec", codec(index = 14))]
MaxNonce,

/// `usize` casting overflow
#[cfg_attr(feature = "with-codec", codec(index = 15))]
UsizeOverflow,
#[cfg_attr(feature = "with-codec", codec(index = 16))]
CreateContractStartingWithEF,
}

impl From<ExitError> for ExitReason {
Expand Down
3 changes: 2 additions & 1 deletion core/src/eval/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub fn exp(op1: U256, op2: U256) -> U256 {
pub fn signextend(op1: U256, op2: U256) -> U256 {
if op1 < U256::from(32) {
// `low_u32` works since op1 < 32
#[allow(clippy::as_conversions)]
let bit_index = (8 * op1.low_u32() + 7) as usize;
let bit = op2.bit(bit_index);
let mask = (U256::one() << bit_index) - U256::one();
Expand Down Expand Up @@ -142,7 +143,7 @@ mod tests {
U256::MAX,
];
for x in 0..64 {
for y in test_values.iter() {
for y in &test_values {
compare_old_signextend(x.into(), *y);
}
}
Expand Down
12 changes: 5 additions & 7 deletions core/src/eval/bitwise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ pub fn shl(shift: U256, value: U256) -> U256 {
if value == U256::zero() || shift >= U256::from(256) {
U256::zero()
} else {
let shift: u64 = shift.as_u64();
value << shift as usize
value << shift.as_usize()
}
}

Expand All @@ -71,8 +70,7 @@ pub fn shr(shift: U256, value: U256) -> U256 {
if value == U256::zero() || shift >= U256::from(256) {
U256::zero()
} else {
let shift: u64 = shift.as_u64();
value >> shift as usize
value >> shift.as_usize()
}
}

Expand All @@ -89,12 +87,12 @@ pub fn sar(shift: U256, value: U256) -> U256 {
Sign::Minus => I256(Sign::Minus, U256::one()).into(),
}
} else {
let shift: u64 = shift.as_u64();
let shift: usize = shift.as_usize();

match value.0 {
Sign::Plus | Sign::Zero => value.1 >> shift as usize,
Sign::Plus | Sign::Zero => value.1 >> shift,
Sign::Minus => {
let shifted = ((value.1.overflowing_sub(U256::one()).0) >> shift as usize)
let shifted = ((value.1.overflowing_sub(U256::one()).0) >> shift)
.overflowing_add(U256::one())
.0;
I256(Sign::Minus, shifted).into()
Expand Down
2 changes: 1 addition & 1 deletion core/src/eval/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub fn mstore8(state: &mut Machine) -> Control {
pop_u256!(state, index, value);
let index = as_usize_or_fail!(index);
try_or_fail!(state.memory.resize_offset(index, 1));
let value = (value.low_u32() & 0xff) as u8;
let value = u8::try_from(value.low_u32() & 0xff).unwrap_or(u8::MAX);
match state.memory.set(index, &[value], Some(1)) {
Ok(()) => Control::Continue(1),
Err(e) => Control::Exit(e.into()),
Expand Down
2 changes: 2 additions & 0 deletions core/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub fn eval<H: InterpreterHandler>(
}

// Table-based interpreter, shows the smallest gas cost.
#[allow(clippy::too_many_lines)]
#[inline]
fn eval_table<H: InterpreterHandler>(
state: &mut Machine,
Expand All @@ -39,6 +40,7 @@ fn eval_table<H: InterpreterHandler>(
state.position = Ok(position + 1);
Control::Trap(opcode)
}
#[allow(clippy::as_conversions)]
let mut table = [eval_external as _; 256];
macro_rules! table_elem {
($operation:ident, $definition:expr) => {
Expand Down
10 changes: 9 additions & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#![deny(warnings)]
#![forbid(unsafe_code, unused_variables, unused_imports)]
#![deny(clippy::pedantic, clippy::nursery)]
#![deny(clippy::as_conversions)]
#![allow(clippy::module_name_repetitions)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(not(feature = "std"))]
Expand Down Expand Up @@ -62,6 +65,8 @@ pub trait InterpreterHandler {

fn after_eval(&mut self);

/// # Errors
/// Return `ExitError`
fn before_bytecode(
&mut self,
opcode: Opcode,
Expand Down Expand Up @@ -169,8 +174,11 @@ impl Machine {
}
}

#[inline]
/// Step the machine, executing until exit or trap.
///
/// # Errors
/// Return `Capture<ExitReason, Trap>`
#[inline]
pub fn step<H: InterpreterHandler>(
&mut self,
handler: &mut H,
Expand Down
27 changes: 24 additions & 3 deletions core/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ use core::cmp::min;
use core::ops::{BitAnd, Not};
use primitive_types::{H256, U256};

/// A sequencial memory. It uses Rust's `Vec` for internal
/// A sequential memory. It uses Rust's `Vec` for internal
/// representation.
#[derive(Clone, Debug)]
pub struct Memory {
/// Memory data
data: Vec<u8>,
/// Memory effective length, that chanded after resize operations.
effective_len: usize,
/// Memory limit
limit: usize,
}

Expand Down Expand Up @@ -57,6 +60,9 @@ impl Memory {

/// Resize the memory, making it cover the memory region of `offset..offset + len`,
/// with 32 bytes as the step. If the length is zero, this function does nothing.
///
/// # Errors
/// Return `ExitError::InvalidRange` if `offset + len` is overflow.
pub fn resize_offset(&mut self, offset: usize, len: usize) -> Result<(), ExitError> {
if len == 0 {
return Ok(());
Expand All @@ -68,6 +74,9 @@ impl Memory {
}

/// Resize the memory, making it cover to `end`, with 32 bytes as the step.
///
/// # Errors
/// Return `ExitError::InvalidRange` if `end` value is overflow in `next_multiple_of_32` call.
pub fn resize_end(&mut self, end: usize) -> Result<(), ExitError> {
if end > self.effective_len {
let new_end = next_multiple_of_32(end).ok_or(ExitError::InvalidRange)?;
Expand Down Expand Up @@ -99,7 +108,7 @@ impl Memory {
ret
}

/// Get `H256` from a specific offset in memory.
/// Get `H256` value from a specific offset in memory.
#[must_use]
pub fn get_h256(&self, offset: usize) -> H256 {
let mut ret = [0; 32];
Expand All @@ -119,6 +128,9 @@ impl Memory {

/// Set memory region at given offset. The offset and value is considered
/// untrusted.
///
/// # Errors
/// Return `ExitFatal::NotSupported` if `offset + target_size` is out of memory limit or overflow.
pub fn set(
&mut self,
offset: usize,
Expand Down Expand Up @@ -154,7 +166,12 @@ impl Memory {
}

/// Copy memory region form `src` to `dst` with length.
/// `copy_within` uses `memmove` to avoid DoS attacks.
/// `copy_within` uses `memmove` to avoid `DoS` attacks.
///
/// # Errors
/// Return `ExitFatal::Other`:
/// - `OverflowOnCopy` if `offset + length` is overflow
/// - `OutOfGasOnCopy` if `offst_length` out of memory limit
pub fn copy(
&mut self,
src_offset: usize,
Expand Down Expand Up @@ -186,6 +203,9 @@ impl Memory {
}

/// Copy `data` into the memory, of given `len`.
///
/// # Errors
/// Return `ExitFatal::NotSupported` if `set()` call return out of memory limit.
pub fn copy_large(
&mut self,
memory_offset: usize,
Expand All @@ -202,6 +222,7 @@ impl Memory {
return Ok(());
}

#[allow(clippy::as_conversions)]
let data = data_offset
.checked_add(len.into())
.map_or(&[] as &[u8], |end| {
Expand Down
2 changes: 2 additions & 0 deletions core/src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,14 @@ impl Opcode {

#[inline]
#[must_use]
#[allow(clippy::as_conversions)]
pub const fn as_usize(&self) -> usize {
self.0 as usize
}
}

impl Display for Opcode {
#[allow(clippy::too_many_lines)]
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let name = match *self {
Self::STOP => "STOP",
Expand Down
Loading

0 comments on commit 226d7eb

Please sign in to comment.