From 2b53a2e471ecc8ebcabd0e700a9468144a5b2ff5 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:22:43 +0200 Subject: [PATCH] docs: document everything, dedup existing docs --- crates/interpreter/Cargo.toml | 9 +- crates/interpreter/src/gas.rs | 6 +- crates/interpreter/src/host.rs | 47 +++++++--- crates/interpreter/src/host/dummy.rs | 1 + crates/interpreter/src/inner_models.rs | 19 ++-- crates/interpreter/src/instructions.rs | 4 +- crates/interpreter/src/instructions/macros.rs | 4 +- crates/interpreter/src/interpreter.rs | 6 +- .../interpreter/src/interpreter/analysis.rs | 1 + .../interpreter/src/interpreter/contract.rs | 1 + crates/interpreter/src/interpreter/memory.rs | 34 +------ crates/interpreter/src/interpreter/stack.rs | 5 +- crates/interpreter/src/lib.rs | 19 ++-- crates/precompile/Cargo.toml | 8 +- crates/precompile/src/lib.rs | 12 ++- crates/precompile/src/secp256k1.rs | 5 +- crates/primitives/Cargo.toml | 12 ++- crates/primitives/src/constants.rs | 7 +- crates/primitives/src/db.rs | 2 + crates/primitives/src/env.rs | 2 +- crates/primitives/src/lib.rs | 19 ++-- crates/primitives/src/result.rs | 9 +- crates/primitives/src/utilities.rs | 52 +++++++++-- crates/revm/src/db.rs | 2 + crates/revm/src/evm_impl.rs | 8 +- crates/revm/src/inspector.rs | 92 ++++++++++++------- crates/revm/src/inspector/customprinter.rs | 7 +- .../{tracer_eip3155.rs => eip3155.rs} | 3 +- crates/revm/src/inspector/gas.rs | 24 +---- crates/revm/src/inspector/noop.rs | 5 +- crates/revm/src/journaled_state.rs | 2 +- crates/revm/src/lib.rs | 3 +- 32 files changed, 242 insertions(+), 188 deletions(-) rename crates/revm/src/inspector/{tracer_eip3155.rs => eip3155.rs} (98%) diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index aa43614127f..28e3af287ba 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Dragan Rakita "] -description = "REVM Interpreter" +description = "EVM bytecode interpreter" edition = "2021" keywords = ["no_std", "ethereum", "evm", "revm", "interpreter"] license = "MIT" @@ -10,7 +10,7 @@ version = "1.1.2" readme = "../../README.md" [dependencies] -revm-primitives = { path = "../primitives", version="1.1.2", default-features = false } +revm-primitives = { path = "../primitives", version = "1.1.2", default-features = false } #utility derive_more = "0.99" @@ -48,10 +48,7 @@ optional_eip3607 = ["revm-primitives/optional_eip3607"] optional_gas_refund = ["revm-primitives/optional_gas_refund"] optional_no_base_fee = ["revm-primitives/optional_no_base_fee"] std = ["revm-primitives/std"] -serde = [ - "dep:serde", - "revm-primitives/serde", -] +serde = ["dep:serde", "revm-primitives/serde"] arbitrary = [ "std", "dep:arbitrary", diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index 79d6f3905dd..350c1ecef17 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -1,5 +1,7 @@ -pub mod calc; -pub mod constants; +//! EVM gas calculation utilities. + +mod calc; +mod constants; pub use calc::*; pub use constants::*; diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 777a84957ee..d81325c1dd2 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -10,48 +10,67 @@ mod dummy; /// EVM context host. pub trait Host { + /// Called before the interpreter executes an instruction. fn step(&mut self, interpreter: &mut Interpreter) -> InstructionResult; + + /// Called after the interpreter executes an instruction. fn step_end( &mut self, interpreter: &mut Interpreter, ret: InstructionResult, ) -> InstructionResult; + /// Returns a mutable reference to the environment. fn env(&mut self) -> &mut Env; - /// load account. Returns (is_cold,is_new_account) + /// Load an account. + /// + /// Returns (is_cold, is_new_account) fn load_account(&mut self, address: B160) -> Option<(bool, bool)>; - /// Get environmental block hash. + + /// Get the block hash of the given block `number`. fn block_hash(&mut self, number: U256) -> Option; - /// Get balance of address and if account is cold loaded. + + /// Get balance of `address` and if the account is cold. fn balance(&mut self, address: B160) -> Option<(U256, bool)>; - /// Get code of address and if account is cold loaded. + + /// Get code of `address` and if the account is cold. fn code(&mut self, address: B160) -> Option<(Bytecode, bool)>; - /// Get code hash of address and if account is cold loaded. + + /// Get code hash of `address` and if the account is cold. fn code_hash(&mut self, address: B160) -> Option<(B256, bool)>; - /// Get storage value of address at index and if account is cold loaded. + + /// Get storage value of `address` at `index` and if the account is cold. fn sload(&mut self, address: B160, index: U256) -> Option<(U256, bool)>; + /// Set storage value of account address at index. - /// Returns (original, present, new, sis_cold) + /// + /// Returns (original, present, new, is_cold). fn sstore( &mut self, address: B160, index: U256, value: U256, ) -> Option<(U256, U256, U256, bool)>; - /// Get the transient storage value of address at index. + + /// Get the transient storage value of `address` at `index`. fn tload(&mut self, address: B160, index: U256) -> U256; - /// Set the transient storage value of address at index. + + /// Set the transient storage value of `address` at `index`. fn tstore(&mut self, address: B160, index: U256, value: U256); - /// Create a log owned by address with given topics and data. + + /// Emit a log owned by `address` with given `topics` and `data`. fn log(&mut self, address: B160, topics: Vec, data: Bytes); - /// Mark an address to be deleted, with funds transferred to target. - fn selfdestruct(&mut self, address: B160, target: B160) -> Option; + + /// Invoke a call operation. + fn call(&mut self, input: &mut CallInputs) -> (InstructionResult, Gas, Bytes); + /// Invoke a create operation. fn create( &mut self, inputs: &mut CreateInputs, ) -> (InstructionResult, Option, Gas, Bytes); - /// Invoke a call operation. - fn call(&mut self, input: &mut CallInputs) -> (InstructionResult, Gas, Bytes); + + /// Mark `address` to be deleted, with funds transferred to `target`. + fn selfdestruct(&mut self, address: B160, target: B160) -> Option; } diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index c2df6b2f653..009a980ac4d 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -5,6 +5,7 @@ use crate::{ }; use alloc::vec::Vec; +/// A dummy [Host] implementation. pub struct DummyHost { pub env: Env, pub storage: HashMap, diff --git a/crates/interpreter/src/inner_models.rs b/crates/interpreter/src/inner_models.rs index 5467876995a..a3fd9eb6851 100644 --- a/crates/interpreter/src/inner_models.rs +++ b/crates/interpreter/src/inner_models.rs @@ -18,20 +18,26 @@ pub struct CallInputs { pub gas_limit: u64, /// The context of the call. pub context: CallContext, - /// Is static call + /// Whether this is a static call. pub is_static: bool, } +/// Inputs for a create call. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateInputs { + /// Caller address of the EVM. pub caller: B160, + /// The create scheme. pub scheme: CreateScheme, + /// The value to transfer. pub value: U256, + /// The init code of the contract. #[cfg_attr( feature = "serde", serde(with = "crate::primitives::utilities::serde_hex_bytes") )] pub init_code: Bytes, + /// The gas limit of the call. pub gas_limit: u64, } @@ -49,13 +55,13 @@ pub enum CallScheme { StaticCall, } -/// CallContext of the runtime. +/// Context of a runtime call. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CallContext { /// Execution address. pub address: B160, - /// Caller of the EVM. + /// Caller address of the EVM. pub caller: B160, /// The address the contract code was loaded from, if any. pub code_address: B160, @@ -81,14 +87,15 @@ impl Default for CallContext { #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Transfer { - /// Source address. + /// The source address. pub source: B160, - /// Target address. + /// The target address. pub target: B160, - /// Transfer value. + /// The transfer value. pub value: U256, } +/// Result of a call that resulted in a self destruct. #[derive(Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SelfDestructResult { diff --git a/crates/interpreter/src/instructions.rs b/crates/interpreter/src/instructions.rs index 5088aa4dd8b..b313f8421d1 100644 --- a/crates/interpreter/src/instructions.rs +++ b/crates/interpreter/src/instructions.rs @@ -1,5 +1,7 @@ +//! EVM opcode implementations. + #[macro_use] -pub mod macros; +mod macros; pub mod arithmetic; pub mod bitwise; diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 052a4a830b1..648d3efd88b 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -52,9 +52,7 @@ macro_rules! gas_or_fail { macro_rules! memory_resize { ($interp:expr, $offset:expr, $len:expr) => { - if let Some(new_size) = - crate::interpreter::memory::next_multiple_of_32($offset.saturating_add($len)) - { + if let Some(new_size) = revm_primitives::next_multiple_of_32($offset.saturating_add($len)) { #[cfg(feature = "memory_limit")] if new_size > ($interp.memory_limit as usize) { $interp.instruction_result = InstructionResult::MemoryLimitOOG; diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index d13bd1998af..429a2db876d 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -1,6 +1,6 @@ pub mod analysis; mod contract; -pub mod memory; +mod memory; mod stack; use crate::primitives::{Bytes, Spec}; @@ -9,9 +9,7 @@ use crate::{alloc::boxed::Box, opcode::eval, Gas, Host, InstructionResult}; pub use analysis::BytecodeLocked; pub use contract::Contract; pub use memory::Memory; -pub use stack::{Stack, STACK_LIMIT}; - -pub const CALL_STACK_LIMIT: u64 = 1024; +pub use stack::Stack; /// EIP-170: Contract code size limit /// diff --git a/crates/interpreter/src/interpreter/analysis.rs b/crates/interpreter/src/interpreter/analysis.rs index d26fa856769..5778470fefb 100644 --- a/crates/interpreter/src/interpreter/analysis.rs +++ b/crates/interpreter/src/interpreter/analysis.rs @@ -58,6 +58,7 @@ fn analyze(code: &[u8]) -> JumpMap { JumpMap(Arc::new(jumps)) } +/// An analyzed bytecode. #[derive(Clone)] pub struct BytecodeLocked { bytecode: Bytes, diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 1467b874cb3..8bfa28490c0 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -2,6 +2,7 @@ use super::analysis::{to_analysed, BytecodeLocked}; use crate::primitives::{Bytecode, Bytes, Env, TransactTo, B160, B256, U256}; use crate::CallContext; +/// EVM contract information. #[derive(Clone, Debug, Default)] pub struct Contract { /// Contracts data diff --git a/crates/interpreter/src/interpreter/memory.rs b/crates/interpreter/src/interpreter/memory.rs index 9982cf60967..48179debffd 100644 --- a/crates/interpreter/src/interpreter/memory.rs +++ b/crates/interpreter/src/interpreter/memory.rs @@ -1,9 +1,5 @@ use crate::{alloc::vec::Vec, primitives::U256}; -use core::{ - cmp::min, - fmt, - ops::{BitAnd, Not}, -}; +use core::{cmp::min, fmt}; /// A sequential memory. It uses Rust's `Vec` for internal /// representation. @@ -183,17 +179,9 @@ impl Memory { } } -/// Rounds up `x` to the closest multiple of 32. If `x % 32 == 0` then `x` is returned. -#[inline] -pub(crate) fn next_multiple_of_32(x: usize) -> Option { - let r = x.bitand(31).not().wrapping_add(1).bitand(31); - x.checked_add(r) -} - #[cfg(test)] mod tests { - use super::next_multiple_of_32; - use crate::Memory; + use super::*; #[test] fn test_copy() { @@ -212,22 +200,4 @@ mod tests { let copied_data = memory.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 - for i in 0..32 { - let x = i * 32; - assert_eq!(Some(x), next_multiple_of_32(x)); - } - - // next_multiple_of_32 rounds up to the nearest multiple of 32 when `x % 32 != 0` - for x in 0..1024 { - if x % 32 == 0 { - continue; - } - let next_multiple = x + 32 - (x % 32); - assert_eq!(Some(next_multiple), next_multiple_of_32(x)); - } - } } diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index 0a3f8a2edbc..8ece1fe71ee 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -1,13 +1,10 @@ use crate::{ - primitives::{B256, U256}, + primitives::{B256, STACK_LIMIT, U256}, InstructionResult, }; use alloc::vec::Vec; use core::fmt; -/// The EVM stack limit, in number of items. -pub const STACK_LIMIT: usize = 1024; - /// EVM stack. #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 7ecbd729d2a..dad3413c03f 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -1,3 +1,7 @@ +//! # revm-interpreter +//! +//! EVM bytecode interpreter. + #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; @@ -7,8 +11,8 @@ mod macros; pub mod gas; mod host; -pub mod inner_models; -pub mod instruction_result; +mod inner_models; +mod instruction_result; pub mod instructions; mod interpreter; @@ -16,14 +20,13 @@ pub(crate) const USE_GAS: bool = !cfg!(feature = "no_gas_measuring"); // Reexport primary types. pub use gas::Gas; -pub use host::{DummyHost, Host}; +pub use host::*; pub use inner_models::*; -pub use instruction_result::InstructionResult; +pub use instruction_result::*; pub use instructions::{opcode, Instruction, OpCode, OPCODE_JUMPMAP}; pub use interpreter::{ - analysis, BytecodeLocked, Contract, Interpreter, Memory, Stack, CALL_STACK_LIMIT, - MAX_CODE_SIZE, MAX_INITCODE_SIZE, + analysis, BytecodeLocked, Contract, Interpreter, Memory, Stack, MAX_CODE_SIZE, + MAX_INITCODE_SIZE, }; - -#[doc(inline)] +#[doc(hidden)] pub use revm_primitives as primitives; diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 576046ed792..3a0a65542e7 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Dragan Rakita "] -description = "REVM Precompiles - Ethereum compatible precompiled contracts" +description = "Implementations of EVM precompiled contracts" edition = "2021" keywords = ["no_std", "ethereum", "evm", "revm", "precompiles"] license = "MIT" @@ -8,9 +8,6 @@ name = "revm-precompile" repository = "https://github.com/bluealloy/revm" version = "2.0.3" -# Don't need to run build script outside of this repo -exclude = ["build.rs", "src/blob/kzg_settings/*.txt"] - [dependencies] revm-primitives = { path = "../primitives", version = "1.1.2", default-features = false } bn = { package = "substrate-bn", version = "0.6", default-features = false } @@ -29,9 +26,6 @@ c-kzg = { git = "https://github.com/ethereum/c-kzg-4844", default-features = fal [dev-dependencies] hex = "0.4" -[build-dependencies] -hex = "0.4" - [features] default = ["secp256k1", "std"] # Used to disable kzg lib as i couldn't make it compile for wasm target diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 46f4c1bb961..5a74cca3896 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -1,4 +1,8 @@ -#![no_std] +//! # revm-precompile +//! +//! Implementations of EVM precompiled contracts. + +#![cfg_attr(not(feature = "std"), no_std)] #[macro_use] extern crate alloc; @@ -15,12 +19,12 @@ mod secp256k1; use alloc::{boxed::Box, vec::Vec}; use core::fmt; use once_cell::race::OnceBox; -pub use primitives::{ +#[doc(hidden)] +pub use revm_primitives as primitives; +pub use revm_primitives::{ precompile::{PrecompileError as Error, *}, Bytes, HashMap, }; -#[doc(inline)] -pub use revm_primitives as primitives; pub type B160 = [u8; 20]; pub type B256 = [u8; 32]; diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 7bd44d09d69..3097f162046 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -1,4 +1,6 @@ use crate::{Error, Precompile, PrecompileAddress, PrecompileResult, StandardPrecompileFn}; +use alloc::vec::Vec; +use core::cmp::min; pub const ECRECOVER: PrecompileAddress = PrecompileAddress( crate::u64_to_b160(1), @@ -60,9 +62,6 @@ mod secp256k1 { } fn ec_recover_run(i: &[u8], target_gas: u64) -> PrecompileResult { - use alloc::vec::Vec; - use core::cmp::min; - const ECRECOVER_BASE: u64 = 3_000; if ECRECOVER_BASE > target_gas { diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 218aeb41e2d..b2a8561a298 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -9,6 +9,9 @@ repository = "https://github.com/bluealloy/revm" version = "1.1.2" readme = "../../README.md" +# Don't need to run build script outside of this repo +exclude = ["build.rs", "src/kzg/*.txt"] + [dependencies] bytes = { version = "1.5", default-features = false } hashbrown = "0.14" @@ -77,7 +80,14 @@ optional_block_gas_limit = [] optional_eip3607 = [] optional_gas_refund = [] optional_no_base_fee = [] -std = ["bytes/std", "rlp/std", "hex/std", "bitvec/std", "bitflags/std", "dep:c-kzg"] +std = [ + "bytes/std", + "rlp/std", + "hex/std", + "bitvec/std", + "bitflags/std", + "dep:c-kzg", +] serde = [ "dep:serde", "hex/serde", diff --git a/crates/primitives/src/constants.rs b/crates/primitives/src/constants.rs index 4e5664747c7..f865e95c0a2 100644 --- a/crates/primitives/src/constants.rs +++ b/crates/primitives/src/constants.rs @@ -1,8 +1,9 @@ use crate::B160; -/// Interpreter stack limit -pub const STACK_LIMIT: u64 = 1024; -/// EVM call stack limit +/// EVM Interpreter stack limit. +pub const STACK_LIMIT: usize = 1024; + +/// EVM call stack limit. pub const CALL_STACK_LIMIT: u64 = 1024; /// EIP-170: Contract code size limit diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index f376bd6f1eb..84c3536c388 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -34,8 +34,10 @@ impl From for WrapDatabaseRef { } } +/// EVM database commit interface. #[auto_impl(&mut, Box)] pub trait DatabaseCommit { + /// Commit changes to the database. fn commit(&mut self, changes: Map); } diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 8d4e58a40a0..bd27859b95c 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -67,7 +67,7 @@ pub struct BlobExcessGasAndPrice { } impl BlobExcessGasAndPrice { - /// Takes excess blob gas and calculated blob fee with [`calc_blob_fee`] + /// Creates a new instance by calculating the blob gas price with [`calc_blob_gasprice`]. pub fn new(excess_blob_gas: u64) -> Self { let blob_gasprice = calc_blob_gasprice(excess_blob_gas); Self { diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index e41ef8b2e87..2c1d90f9e91 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -1,23 +1,26 @@ +//! # revm-primitives +//! +//! EVM primitive types. + #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; -pub mod bits; -pub mod bytecode; -pub mod constants; +mod bits; +mod bytecode; +mod constants; pub mod db; -pub mod env; +mod env; #[cfg(feature = "std")] pub mod kzg; -pub mod log; +mod log; pub mod precompile; pub mod result; pub mod specification; pub mod state; pub mod utilities; -pub use bits::B160; -pub use bits::B256; +pub use bits::*; pub use bitvec; pub use bytecode::*; pub use bytes; @@ -29,7 +32,7 @@ pub use hex; pub use hex_literal; #[cfg(feature = "std")] pub use kzg::{EnvKzgSettings, KzgSettings}; -pub use log::Log; +pub use log::*; pub use precompile::*; pub use result::*; pub use ruint; diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index d7ed3f21333..62307cf5173 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -15,6 +15,7 @@ pub struct ResultAndState { pub state: State, } +/// Result of a transaction execution. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ExecutionResult { @@ -91,6 +92,7 @@ impl ExecutionResult { } } +/// Output of a transaction execution. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Output { @@ -120,11 +122,15 @@ impl Output { } } +/// EVM error. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum EVMError { + /// Transaction validation error. Transaction(InvalidTransaction), + /// Header validation error. Header(InvalidHeader), + /// Database error. Database(DBError), } @@ -147,6 +153,7 @@ impl From for EVMError { } } +/// Transaction validation error. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InvalidTransaction { @@ -214,7 +221,7 @@ impl From for EVMError { } } -/// Errors related to misconfiguration of the `BlockEnv` +/// Errors related to misconfiguration of a [`BlockEnv`]. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InvalidHeader { diff --git a/crates/primitives/src/utilities.rs b/crates/primitives/src/utilities.rs index a1469fc8df8..7a17fe0cf7b 100644 --- a/crates/primitives/src/utilities.rs +++ b/crates/primitives/src/utilities.rs @@ -1,6 +1,7 @@ use crate::{ B160, B256, BLOB_GASPRICE_UPDATE_FRACTION, MIN_BLOB_GASPRICE, TARGET_BLOB_GAS_PER_BLOCK, U256, }; +use core::ops::{BitAnd, Not}; use hex_literal::hex; use sha3::{Digest, Keccak256}; @@ -8,12 +9,15 @@ pub const KECCAK_EMPTY: B256 = B256(hex!( "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" )); -#[inline(always)] +/// Simple interface to the [`Keccak-256`] hash function. +/// +/// [`Keccak-256`]: https://en.wikipedia.org/wiki/SHA-3 +#[inline] pub fn keccak256(input: &[u8]) -> B256 { - B256(Keccak256::digest(input)[..].try_into().unwrap()) + B256(Keccak256::digest(input).into()) } -/// Returns the address for the legacy `CREATE` scheme: [`crate::env::CreateScheme::Create`] +/// Returns the address for the legacy [`CREATE`](crate::env::CreateScheme::Create) scheme. pub fn create_address(caller: B160, nonce: u64) -> B160 { let mut stream = rlp::RlpStream::new_list(2); stream.append(&caller.0.as_ref()); @@ -22,7 +26,7 @@ pub fn create_address(caller: B160, nonce: u64) -> B160 { B160(out[12..].try_into().unwrap()) } -/// Returns the address for the `CREATE2` scheme: [`crate::env::CreateScheme::Create2`] +/// Returns the address for the [`CREATE2`](crate::env::CreateScheme::Create2) scheme. pub fn create2_address(caller: B160, code_hash: B256, salt: U256) -> B160 { let mut hasher = Keccak256::new(); hasher.update([0xff]); @@ -35,15 +39,17 @@ pub fn create2_address(caller: B160, code_hash: B256, salt: U256) -> B160 { /// Calculates the `excess_blob_gas` from the parent header's `blob_gas_used` and `excess_blob_gas`. /// -/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers). +/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers +/// (`calc_excess_blob_gas`). #[inline] pub fn calc_excess_blob_gas(parent_excess_blob_gas: u64, parent_blob_gas_used: u64) -> u64 { (parent_excess_blob_gas + parent_blob_gas_used).saturating_sub(TARGET_BLOB_GAS_PER_BLOCK) } -/// Calculates the blob gasprice from the header's excess blob gas field. +/// Calculates the blob gas price from the header's excess blob gas field. /// -/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers). +/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers) +/// (`get_blob_gasprice`). #[inline] pub fn calc_blob_gasprice(excess_blob_gas: u64) -> u64 { fake_exponential( @@ -57,11 +63,12 @@ pub fn calc_blob_gasprice(excess_blob_gas: u64) -> u64 { /// /// This is used to calculate the blob price. /// -/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers). +/// See also [the EIP-4844 helpers](https://eips.ethereum.org/EIPS/eip-4844#helpers) +/// (`fake_exponential`). /// -/// # Panic +/// # Panics /// -/// Panics if `denominator` is zero. +/// This function panics if `denominator` is zero. #[inline] pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u64 { assert_ne!(denominator, 0, "attempt to divide by zero"); @@ -82,6 +89,13 @@ pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u64 { (output / denominator) as u64 } +/// Rounds up `x` to the closest multiple of 32. If `x % 32 == 0` then `x` is returned. +#[inline] +pub fn next_multiple_of_32(x: usize) -> Option { + let r = x.bitand(31).not().wrapping_add(1).bitand(31); + x.checked_add(r) +} + /// Serde functions to serde as [bytes::Bytes] hex string #[cfg(feature = "serde")] pub mod serde_hex_bytes { @@ -204,4 +218,22 @@ mod tests { assert_eq!(actual, expected, "test: {t:?}"); } } + + #[test] + fn test_next_multiple_of_32() { + // next_multiple_of_32 returns x when it is a multiple of 32 + for i in 0..32 { + let x = i * 32; + assert_eq!(Some(x), next_multiple_of_32(x)); + } + + // next_multiple_of_32 rounds up to the nearest multiple of 32 when `x % 32 != 0` + for x in 0..1024 { + if x % 32 == 0 { + continue; + } + let next_multiple = x + 32 - (x % 32); + assert_eq!(Some(next_multiple), next_multiple_of_32(x)); + } + } } diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index 72f35cc848a..9d6494701e8 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -1,3 +1,5 @@ +//! [Database] implementations. + pub mod emptydb; #[cfg(feature = "ethersdb")] pub mod ethersdb; diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 6927cddbede..76bf9e0b939 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,13 +1,13 @@ use crate::interpreter::{ - analysis::to_analysed, gas, instruction_result::SuccessOrHalt, return_ok, return_revert, - CallContext, CallInputs, CallScheme, Contract, CreateInputs, CreateScheme, Gas, Host, - InstructionResult, Interpreter, SelfDestructResult, Transfer, CALL_STACK_LIMIT, + analysis::to_analysed, gas, return_ok, return_revert, CallContext, CallInputs, CallScheme, + Contract, CreateInputs, CreateScheme, Gas, Host, InstructionResult, Interpreter, + SelfDestructResult, SuccessOrHalt, Transfer, }; use crate::journaled_state::{is_precompile, JournalCheckpoint}; use crate::primitives::{ create2_address, create_address, keccak256, Account, AnalysisKind, Bytecode, Bytes, EVMError, EVMResult, Env, ExecutionResult, HashMap, InvalidTransaction, Log, Output, ResultAndState, - Spec, SpecId::*, TransactTo, B160, B256, U256, + Spec, SpecId::*, TransactTo, B160, B256, CALL_STACK_LIMIT, U256, }; use crate::{db::Database, journaled_state::JournaledState, precompile, Inspector}; use alloc::boxed::Box; diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 9d0671953fa..bf249dcbb1c 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,41 +1,40 @@ use crate::evm_impl::EVMData; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}; use crate::primitives::{db::Database, Bytes, B160, B256, U256}; - use auto_impl::auto_impl; #[cfg(feature = "std")] mod customprinter; +#[cfg(all(feature = "std", feature = "serde"))] +mod eip3155; mod gas; mod noop; -#[cfg(all(feature = "std", feature = "serde"))] -mod tracer_eip3155; -/// All Inspectors implementations that revm has. +/// [Inspector] implementations. pub mod inspectors { #[cfg(feature = "std")] - #[doc(inline)] pub use super::customprinter::CustomPrintTracer; - #[doc(inline)] + #[cfg(all(feature = "std", feature = "serde"))] + pub use super::eip3155::TracerEip3155; pub use super::gas::GasInspector; - #[doc(inline)] pub use super::noop::NoOpInspector; - #[cfg(all(feature = "std", feature = "serde"))] - #[doc(inline)] - pub use super::tracer_eip3155::TracerEip3155; } +/// EVM [Interpreter] callbacks. #[auto_impl(&mut, Box)] pub trait Inspector { - /// Called Before the interpreter is initialized. + /// Called before the interpreter is initialized. /// /// If anything other than [InstructionResult::Continue] is returned then execution of the interpreter is /// skipped. + #[inline] fn initialize_interp( &mut self, - _interp: &mut Interpreter, - _data: &mut EVMData<'_, DB>, + interp: &mut Interpreter, + data: &mut EVMData<'_, DB>, ) -> InstructionResult { + let _ = interp; + let _ = data; InstructionResult::Continue } @@ -47,44 +46,55 @@ pub trait Inspector { /// # Example /// /// To get the current opcode, use `interp.current_opcode()`. - fn step( - &mut self, - _interp: &mut Interpreter, - _data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + #[inline] + fn step(&mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>) -> InstructionResult { + let _ = interp; + let _ = data; InstructionResult::Continue } /// Called when a log is emitted. + #[inline] fn log( &mut self, - _evm_data: &mut EVMData<'_, DB>, - _address: &B160, - _topics: &[B256], - _data: &Bytes, + evm_data: &mut EVMData<'_, DB>, + address: &B160, + topics: &[B256], + data: &Bytes, ) { + let _ = evm_data; + let _ = address; + let _ = topics; + let _ = data; } /// Called after `step` when the instruction has been executed. /// /// InstructionResulting anything other than [InstructionResult::Continue] alters the execution of the interpreter. + #[inline] fn step_end( &mut self, - _interp: &mut Interpreter, - _data: &mut EVMData<'_, DB>, - _eval: InstructionResult, + interp: &mut Interpreter, + data: &mut EVMData<'_, DB>, + eval: InstructionResult, ) -> InstructionResult { + let _ = interp; + let _ = data; + let _ = eval; InstructionResult::Continue } /// Called whenever a call to a contract is about to start. /// /// InstructionResulting anything other than [InstructionResult::Continue] overrides the result of the call. + #[inline] fn call( &mut self, - _data: &mut EVMData<'_, DB>, - _inputs: &mut CallInputs, + data: &mut EVMData<'_, DB>, + inputs: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { + let _ = data; + let _ = inputs; (InstructionResult::Continue, Gas::new(0), Bytes::new()) } @@ -92,25 +102,31 @@ pub trait Inspector { /// /// InstructionResulting anything other than the values passed to this function (`(ret, remaining_gas, /// out)`) will alter the result of the call. + #[inline] fn call_end( &mut self, - _data: &mut EVMData<'_, DB>, - _inputs: &CallInputs, + data: &mut EVMData<'_, DB>, + inputs: &CallInputs, remaining_gas: Gas, ret: InstructionResult, out: Bytes, ) -> (InstructionResult, Gas, Bytes) { + let _ = data; + let _ = inputs; (ret, remaining_gas, out) } /// Called when a contract is about to be created. /// /// InstructionResulting anything other than [InstructionResult::Continue] overrides the result of the creation. + #[inline] fn create( &mut self, - _data: &mut EVMData<'_, DB>, - _inputs: &mut CreateInputs, + data: &mut EVMData<'_, DB>, + inputs: &mut CreateInputs, ) -> (InstructionResult, Option, Gas, Bytes) { + let _ = data; + let _ = inputs; ( InstructionResult::Continue, None, @@ -123,18 +139,26 @@ pub trait Inspector { /// /// InstructionResulting anything other than the values passed to this function (`(ret, remaining_gas, /// address, out)`) will alter the result of the create. + #[inline] fn create_end( &mut self, - _data: &mut EVMData<'_, DB>, - _inputs: &CreateInputs, + data: &mut EVMData<'_, DB>, + inputs: &CreateInputs, ret: InstructionResult, address: Option, remaining_gas: Gas, out: Bytes, ) -> (InstructionResult, Option, Gas, Bytes) { + let _ = data; + let _ = inputs; (ret, address, remaining_gas, out) } /// Called when a contract has been self-destructed with funds transferred to target. - fn selfdestruct(&mut self, _contract: B160, _target: B160, _value: U256) {} + #[inline] + fn selfdestruct(&mut self, contract: B160, target: B160, value: U256) { + let _ = contract; + let _ = target; + let _ = value; + } } diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index ba69bdf2494..aa62bbf3d0d 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -1,9 +1,10 @@ -//! Custom print inspector, it has step level information of execution. -//! It is a great tool if some debugging is needed. -//! use crate::interpreter::{opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}; use crate::primitives::{hex, Bytes, B160, U256}; use crate::{inspectors::GasInspector, Database, EVMData, Inspector}; + +/// Custom print [Inspector], it has step level information of execution. +/// +/// It is a great tool if some debugging is needed. #[derive(Clone, Default)] pub struct CustomPrintTracer { gas_inspector: GasInspector, diff --git a/crates/revm/src/inspector/tracer_eip3155.rs b/crates/revm/src/inspector/eip3155.rs similarity index 98% rename from crates/revm/src/inspector/tracer_eip3155.rs rename to crates/revm/src/inspector/eip3155.rs index cd8ff0f3b8c..4747f1610d7 100644 --- a/crates/revm/src/inspector/tracer_eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -1,5 +1,3 @@ -//! Inspector that support tracing of EIP-3155 - use crate::inspectors::GasInspector; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult}; use crate::primitives::{db::Database, hex, Bytes, B160}; @@ -9,6 +7,7 @@ use revm_interpreter::{opcode, Interpreter, Memory, Stack}; use serde_json::json; use std::io::Write; +/// [EIP-3155](https://eips.ethereum.org/EIPS/eip-3155) tracer [Inspector]. pub struct TracerEip3155 { output: Box, gas_inspector: GasInspector, diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 7886ed00be3..8c71238d136 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -1,9 +1,8 @@ -//! GasIspector. Helper Inspector to calculate gas for others. -//! use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult}; use crate::primitives::{db::Database, Bytes, B160}; use crate::{evm_impl::EVMData, Inspector}; +/// Helper [Inspector] that keeps track of gas. #[allow(dead_code)] #[derive(Clone, Copy, Debug, Default)] pub struct GasInspector { @@ -32,18 +31,6 @@ impl Inspector for GasInspector { InstructionResult::Continue } - // get opcode by calling `interp.contract.opcode(interp.program_counter())`. - // all other information can be obtained from interp. - - #[cfg(not(feature = "no_gas_measuring"))] - fn step( - &mut self, - _interp: &mut crate::interpreter::Interpreter, - _data: &mut EVMData<'_, DB>, - ) -> InstructionResult { - InstructionResult::Continue - } - #[cfg(not(feature = "no_gas_measuring"))] fn step_end( &mut self, @@ -51,13 +38,8 @@ impl Inspector for GasInspector { _data: &mut EVMData<'_, DB>, _eval: InstructionResult, ) -> InstructionResult { - let last_gas = self.gas_remaining; - self.gas_remaining = interp.gas.remaining(); - if last_gas > self.gas_remaining { - self.last_gas_cost = last_gas - self.gas_remaining; - } else { - self.last_gas_cost = 0; - } + let last_gas = core::mem::replace(&mut self.gas_remaining, interp.gas.remaining()); + self.last_gas_cost = last_gas.saturating_sub(self.last_gas_cost); InstructionResult::Continue } diff --git a/crates/revm/src/inspector/noop.rs b/crates/revm/src/inspector/noop.rs index 12123b47f37..05d7292fc4e 100644 --- a/crates/revm/src/inspector/noop.rs +++ b/crates/revm/src/inspector/noop.rs @@ -1,8 +1,7 @@ -//! Dummy NoOp Inspector, helpful as standalone replacement. - use crate::{Database, Inspector}; -#[derive(Clone, Copy)] +/// Dummy [Inspector], helpful as standalone replacement. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoOpInspector; impl Inspector for NoOpInspector {} diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index c866f38ac14..ab74e6b6169 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -1,4 +1,4 @@ -use crate::interpreter::{inner_models::SelfDestructResult, InstructionResult}; +use crate::interpreter::{InstructionResult, SelfDestructResult}; use crate::primitives::{ db::Database, hash_map::Entry, Account, Bytecode, HashMap, Log, Spec, SpecId::*, State, StorageSlot, TransientStorage, B160, KECCAK_EMPTY, PRECOMPILE3, U256, diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 6b93b8705b9..2beca2c580d 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -39,5 +39,4 @@ pub use revm_interpreter as interpreter; pub use revm_interpreter::primitives; // reexport inspector implementations -pub use inspector::inspectors; -pub use inspector::Inspector; +pub use inspector::{inspectors, Inspector};