Skip to content

Commit

Permalink
Merge branch 'waylon/EIP4844' of github.com:/0xJepsen/revm into waylo…
Browse files Browse the repository at this point in the history
…n/EIP4844
  • Loading branch information
0xJepsen committed Jul 3, 2023
2 parents 422ef45 + 81bde72 commit 6581bf8
Show file tree
Hide file tree
Showing 12 changed files with 507 additions and 313 deletions.
694 changes: 389 additions & 305 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bins/revme/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ version = "0.2.0"
[dependencies]
bytes = "1.4"
hash-db = "0.15"
hashbrown = "0.13"
hashbrown = "0.14"
hex = "0.4"
indicatif = "0.17"
plain_hasher = "0.2"
Expand Down
4 changes: 3 additions & 1 deletion bins/revme/src/statetest/models/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum SpecName {
London,
Merge,
Shanghai,
Cancun,
#[serde(other)]
Unknown,
}
Expand All @@ -41,7 +42,8 @@ impl SpecName {
Self::Berlin => SpecId::BERLIN,
Self::London | Self::BerlinToLondonAt5 => SpecId::LONDON,
Self::Merge => SpecId::MERGE,
Self::Shanghai => SpecId::CANCUN,
Self::Shanghai => SpecId::SHANGHAI,
Self::Cancun => SpecId::CANCUN,
Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => {
panic!("Overriden with PETERSBURG")
}
Expand Down
30 changes: 30 additions & 0 deletions crates/interpreter/src/instruction_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,36 @@ pub enum InstructionResult {
FatalExternalError,
}

impl InstructionResult {
pub fn is_error(&self) -> bool {
matches!(
self,
Self::OutOfGas
| Self::MemoryOOG
| Self::MemoryLimitOOG
| Self::PrecompileOOG
| Self::InvalidOperandOOG
| Self::OpcodeNotFound
| Self::CallNotAllowedInsideStatic
| Self::StateChangeDuringStaticCall
| Self::InvalidFEOpcode
| Self::InvalidJump
| Self::NotActivated
| Self::StackUnderflow
| Self::StackOverflow
| Self::OutOfOffset
| Self::CreateCollision
| Self::OverflowPayment
| Self::PrecompileError
| Self::NonceOverflow
| Self::CreateContractSizeLimit
| Self::CreateContractStartingWithEF
| Self::CreateInitcodeSizeLimit
| Self::FatalExternalError
)
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SuccessOrHalt {
Success(Eval),
Expand Down
1 change: 1 addition & 0 deletions crates/interpreter/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub fn eval<H: Host, S: Spec>(opcode: u8, interp: &mut Interpreter, host: &mut H
opcode::DELEGATECALL => host::delegate_call::<S>(interp, host), //check
opcode::STATICCALL => host::static_call::<S>(interp, host), //check
opcode::CHAINID => host_env::chainid::<S>(interp, host),
opcode::MCOPY => memory::mcopy::<S>(interp, host),
opcode::BLOBHASH => memory::blob_hash(interp, host),
_ => return_not_found(interp, host),
}
Expand Down
38 changes: 38 additions & 0 deletions crates/interpreter/src/instructions/memory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
use core::ops::Index;

use crate::{gas, interpreter::Interpreter, primitives::U256, Host, InstructionResult};
use core::cmp::max;

use revm_primitives::SpecId::CANCUN;

use crate::{
gas,
interpreter::Interpreter,
primitives::{Spec, U256},
Host, InstructionResult,
};


pub fn mload(interpreter: &mut Interpreter, _host: &mut dyn Host) {
gas!(interpreter, gas::VERYLOW);
Expand Down Expand Up @@ -37,6 +48,33 @@ pub fn msize(interpreter: &mut Interpreter, _host: &mut dyn Host) {
gas!(interpreter, gas::BASE);
push!(interpreter, U256::from(interpreter.memory.effective_len()));
}

// From EIP-5656 MCOPY
pub fn mcopy<SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut dyn Host) {
// Opcode enabled in Cancun.
// EIP-5656: MCOPY - Memory copying instruction
check!(interpreter, SPEC::enabled(CANCUN));
// get src and dest and length from stack
pop!(interpreter, dest, src, len);

// into usize or fail
let len = as_usize_or_fail!(interpreter, len, InstructionResult::InvalidOperandOOG);
// deduce gas
gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64));
if len == 0 {
return;
}

let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidOperandOOG);
let src = as_usize_or_fail!(interpreter, src, InstructionResult::InvalidOperandOOG);
// memory resize
let resize = max(dest, len).saturating_add(len);
// resize memory
memory_resize!(interpreter, src, resize);
// copy memory in place
interpreter.memory.copy(src, dest, len);
}

pub fn blob_hash(interpreter: &mut Interpreter, host: &mut dyn Host) {
pop!(interpreter, index);
let index = as_usize_or_fail!(interpreter, index, InstructionResult::InvalidOperandOOG);
Expand Down
5 changes: 3 additions & 2 deletions crates/interpreter/src/instructions/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub const JUMPI: u8 = 0x57;
pub const PC: u8 = 0x58;
pub const MSIZE: u8 = 0x59;
pub const JUMPDEST: u8 = 0x5b;
pub const MCOPY: u8 = 0x5e;
pub const PUSH0: u8 = 0x5f;
pub const PUSH1: u8 = 0x60;
pub const PUSH2: u8 = 0x61;
Expand Down Expand Up @@ -277,7 +278,7 @@ pub const OPCODE_JUMPMAP: [Option<&'static str>; 256] = [
/* 0x5b */ Some("JUMPDEST"),
/* 0x5c */ None,
/* 0x5d */ None,
/* 0x5e */ None,
/* 0x5e */ Some("MCOPY"),
/* 0x5f */ Some("PUSH0"),
/* 0x60 */ Some("PUSH1"),
/* 0x61 */ Some("PUSH2"),
Expand Down Expand Up @@ -659,7 +660,7 @@ macro_rules! gas_opcodee {
OpInfo::jumpdest(),
/* 0x5c */ OpInfo::none(),
/* 0x5d */ OpInfo::none(),
/* 0x5e */ OpInfo::none(),
/* 0x5e MCOPY */ OpInfo::dynamic_gas(),
/* 0x5f PUSH0 */
OpInfo::gas(if SpecId::enabled($spec_id, SpecId::SHANGHAI) {
gas::BASE
Expand Down
29 changes: 29 additions & 0 deletions crates/interpreter/src/interpreter/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ impl Memory {
*i = 0;
}
}

/// In memory copy given a src, dst, and length
///
/// # Safety
/// The caller is responsible to check that we resized memory properly.
#[inline(always)]
pub fn copy(&mut self, dst: usize, src: usize, length: usize) {
self.data.copy_within(src..src + length, dst);
}
}

/// Rounds up `x` to the closest multiple of 32. If `x % 32 == 0` then `x` is returned.
Expand All @@ -121,8 +130,28 @@ pub(crate) fn next_multiple_of_32(x: usize) -> Option<usize> {

#[cfg(test)]
mod tests {
use crate::Memory;

use super::next_multiple_of_32;

#[test]
fn test_copy() {
// Create a sample memory instance
let mut memory = Memory::new();

// Set up initial memory data
let data: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
memory.resize(data.len());
memory.set_data(0, 0, data.len(), &data);

// Perform a copy operation
memory.copy(5, 0, 4);

// Verify the copied data
let copied_data = memory.get_slice(5, 4);
assert_eq!(copied_data, &[1, 2, 3, 4]);
}

#[test]
fn test_next_multiple_of_32() {
// next_multiple_of_32 returns x when it is a multiple of 32
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ readme = "../../README.md"

[dependencies]
bytes = { version = "1.4", default-features = false }
hashbrown = { version = "0.13" }
hashbrown = { version = "0.14" }
hex = { version = "0.4", default-features = false }
primitive-types = { version = "0.12", default-features = false }
rlp = { version = "0.5", default-features = false } # used for create2 address calculation
Expand Down
1 change: 1 addition & 0 deletions crates/primitives/src/specification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ impl From<&str> for SpecId {
"London" => SpecId::LONDON,
"Merge" => SpecId::MERGE,
"Shanghai" => SpecId::SHANGHAI,
"Cancun" => SpecId::CANCUN,
_ => SpecId::LATEST,
}
}
Expand Down
4 changes: 3 additions & 1 deletion crates/revm/src/db/in_memory_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ impl Default for InMemoryDB {
///
/// This implementation wraps a [DatabaseRef] that is used to load data ([AccountInfo]).
///
/// Accounts and code are stored in two separate maps, the `accounts` map maps addresses to [DbAccount], whereas contracts are identified by their code hash, and are stored in the `contracts` map. The [DbAccount] holds the code hash of the contract, which is used to look up the contract in the `contracts` map.
/// Accounts and code are stored in two separate maps, the `accounts` map maps addresses to [DbAccount],
/// whereas contracts are identified by their code hash, and are stored in the `contracts` map.
/// The [DbAccount] holds the code hash of the contract, which is used to look up the contract in the `contracts` map.
#[derive(Debug, Clone)]
pub struct CacheDB<ExtDB: DatabaseRef> {
/// Account info where None means it is not existing. Not existing state is needed for Pre TANGERINE forks.
Expand Down
10 changes: 8 additions & 2 deletions crates/revm/src/inspector/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,17 @@ impl<DB: Database> Inspector<DB> for GasInspector {
&mut self,
_data: &mut EVMData<'_, DB>,
_inputs: &CallInputs,
remaining_gas: Gas,
mut remaining_gas: Gas,
ret: InstructionResult,
out: Bytes,
) -> (InstructionResult, Gas, Bytes) {
(ret, remaining_gas, out)
if ret.is_error() {
remaining_gas.record_cost(remaining_gas.remaining());
self.gas_remaining = 0;
(ret, remaining_gas, out)
} else {
(ret, remaining_gas, out)
}
}

fn create_end(
Expand Down

0 comments on commit 6581bf8

Please sign in to comment.