diff --git a/Cargo.lock b/Cargo.lock index 01513172b0..af92c58a71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,17 +43,52 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-primitives" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4084879b7257d5b95b9009837c07a1868bd7d60e66418a7764b9b580ae64e0" +dependencies = [ + "alloy-rlp", + "arbitrary", + "bytes", + "cfg-if", + "const-hex", + "derive_arbitrary", + "derive_more", + "hex-literal", + "itoa", + "proptest", + "proptest-derive", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + [[package]] name = "alloy-rlp" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f938f00332d63a5b0ac687bd6f46d03884638948921d9f8b50c59563d421ae25" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", "smol_str", ] +[[package]] +name = "alloy-rlp-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -92,9 +127,6 @@ name = "arbitrary" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" -dependencies = [ - "derive_arbitrary", -] [[package]] name = "ark-ff" @@ -2325,14 +2357,11 @@ version = "3.4.0" dependencies = [ "anyhow", "auto_impl", - "bytes", "criterion", "ethers-contract", "ethers-core", "ethers-providers", "futures", - "hex", - "hex-literal", "revm-interpreter", "revm-precompile", "serde", @@ -2344,14 +2373,8 @@ dependencies = [ name = "revm-interpreter" version = "1.2.0" dependencies = [ - "arbitrary", - "derive_more", - "enumn", - "proptest", - "proptest-derive", "revm-primitives", "serde", - "sha3", ] [[package]] @@ -2359,7 +2382,6 @@ name = "revm-precompile" version = "2.1.0" dependencies = [ "c-kzg", - "hex", "k256", "num", "once_cell", @@ -2367,7 +2389,6 @@ dependencies = [ "ripemd", "secp256k1", "sha2", - "sha3", "substrate-bn", ] @@ -2375,46 +2396,32 @@ dependencies = [ name = "revm-primitives" version = "1.2.0" dependencies = [ - "arbitrary", + "alloy-primitives", + "alloy-rlp", "auto_impl", "bitflags 2.4.0", "bitvec", - "bytes", "c-kzg", - "derive_more", "enumn", - "fixed-hash", "hashbrown 0.14.1", "hex", - "hex-literal", "once_cell", - "primitive-types", - "proptest", - "proptest-derive", - "rlp", - "ruint", "serde", - "sha3", ] [[package]] name = "revme" version = "0.2.0" dependencies = [ - "bytes", + "alloy-rlp", "hash-db", "hashbrown 0.14.1", - "hex", - "hex-literal", "indicatif", "plain_hasher", - "primitive-types", "revm", - "rlp", "ruint", "serde", "serde_json", - "sha3", "structopt", "thiserror", "triehash", diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 4e07fe0a2a..a0a1200dd9 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -10,25 +10,22 @@ version = "0.2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bytes = "1.5" hash-db = "0.15" hashbrown = "0.14" -hex = "0.4" indicatif = "0.17" plain_hasher = "0.2" -primitive-types = { version = "0.12", features = ["rlp", "serde"] } revm = { path = "../../crates/revm", version = "3.4.0", default-features = false, features = [ "ethersdb", "std", "serde", ] } -rlp = { version = "0.5", default-features = false } -ruint = { version = "1.8.0", features = ["rlp", "serde"] } +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"] } -sha3 = { version = "0.10", default-features = false } structopt = "0.3" thiserror = "1.0" triehash = "0.8" walkdir = "2.4" -hex-literal = "0.4" diff --git a/bins/revme/src/cli_env.rs b/bins/revme/src/cli_env.rs index dd48f11c8d..9ab82dc3d3 100644 --- a/bins/revme/src/cli_env.rs +++ b/bins/revme/src/cli_env.rs @@ -1,7 +1,4 @@ -use std::str::FromStr; - -use bytes::Bytes; -use revm::primitives::{Env, TransactTo, B160, U256}; +use revm::primitives::{Address, Bytes, Env, TransactTo, U256}; use structopt::StructOpt; #[derive(StructOpt, Clone, Debug)] @@ -63,8 +60,8 @@ pub struct CliEnvBlock { pub number: Option, /// Coinbase or miner or address that created and signed the block. /// Address where we are going to send gas spend - #[structopt(long = "env.block.coinbase", parse(try_from_str = parse_b160))] - pub coinbase: Option, + #[structopt(long = "env.block.coinbase")] + pub coinbase: Option
, #[structopt(long = "env.block.timestamp")] pub timestamp: Option, #[structopt(long = "env.block.difficulty")] @@ -77,32 +74,24 @@ pub struct CliEnvBlock { #[derive(StructOpt, Clone, Debug)] pub struct CliEnvTx { /// Caller or Author or tx signer - #[structopt(long = "env.tx.caller", parse(try_from_str = parse_b160))] - pub caller: Option, + #[structopt(long = "env.tx.caller")] + pub caller: Option
, #[structopt(long = "env.tx.gas_limit")] pub tx_gas_limit: Option, #[structopt(long = "env.tx.gas_price")] pub gas_price: Option, #[structopt(long = "env.tx.gas_priority_fee")] pub gas_priority_fee: Option, - #[structopt(long = "env.tx.to", parse(try_from_str = parse_b160))] - pub transact_to: Option, + #[structopt(long = "env.tx.to")] + pub transact_to: Option
, #[structopt(long = "env.tx.value")] pub value: Option, - #[structopt(long = "env.tx.data", parse(try_from_str = parse_hex))] + #[structopt(long = "env.tx.data")] pub data: Option, #[structopt(long = "env.tx.chain_id")] pub chain_id: Option, #[structopt(long = "env.tx.nonce")] pub nonce: Option, //#[structopt(long = "env.")] - //TODO pub access_list: Vec<(B160, Vec)>, -} - -fn parse_hex(src: &str) -> Result { - Ok(Bytes::from(hex::decode(src)?)) -} - -pub fn parse_b160(input: &str) -> Result::Err> { - B160::from_str(input) + //TODO pub access_list: Vec<(Address, Vec)>, } diff --git a/bins/revme/src/statetest/merkle_trie.rs b/bins/revme/src/statetest/merkle_trie.rs index b37ec4a2ee..cda0bfd2e1 100644 --- a/bins/revme/src/statetest/merkle_trie.rs +++ b/bins/revme/src/statetest/merkle_trie.rs @@ -1,79 +1,74 @@ -use bytes::Bytes; +use alloy_rlp::{RlpEncodable, RlpMaxEncodedLen}; use hash_db::Hasher; use plain_hasher::PlainHasher; -use primitive_types::{H160, H256}; use revm::{ db::PlainAccount, - primitives::{keccak256, Log, B160, B256, U256}, + primitives::{keccak256, Address, Log, B256, U256}, }; -use rlp::RlpStream; -use sha3::{Digest, Keccak256}; use triehash::sec_trie_root; -pub fn log_rlp_hash(logs: Vec) -> B256 { - //https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/cmd/evm/internal/t8ntool/execution.go#L255 - let mut stream = RlpStream::new(); - stream.begin_unbounded_list(); - for log in logs { - stream.begin_list(3); - stream.append(&log.address.0.as_ref()); - stream.begin_unbounded_list(); - for topic in log.topics { - stream.append(&topic.0.as_ref()); - } - stream.finalize_unbounded_list(); - stream.append(&log.data); - } - stream.finalize_unbounded_list(); - let out = stream.out().freeze(); - +pub fn log_rlp_hash(logs: &[Log]) -> B256 { + let mut out = Vec::with_capacity(alloy_rlp::list_length(logs)); + alloy_rlp::encode_list(logs, &mut out); keccak256(&out) } pub fn state_merkle_trie_root<'a>( - accounts: impl IntoIterator, + accounts: impl IntoIterator, ) -> B256 { - let vec = accounts - .into_iter() - .map(|(address, info)| { - let acc_root = trie_account_rlp(info); - (H160::from(address.0), acc_root) - }) - .collect(); + trie_root(accounts.into_iter().map(|(address, acc)| { + ( + address, + alloy_rlp::encode_fixed_size(&TrieAccount::new(acc)), + ) + })) +} - trie_root(vec) +#[derive(RlpEncodable, RlpMaxEncodedLen)] +struct TrieAccount { + nonce: u64, + balance: U256, + root_hash: B256, + code_hash: B256, } -/// Returns the RLP for this account. -pub fn trie_account_rlp(acc: &PlainAccount) -> Bytes { - let mut stream = RlpStream::new_list(4); - stream.append(&acc.info.nonce); - stream.append(&acc.info.balance); - stream.append(&{ - sec_trie_root::( - acc.storage - .iter() - .filter(|(_k, &v)| v != U256::ZERO) - .map(|(&k, v)| (H256::from(k.to_be_bytes()), rlp::encode(v))), - ) - }); - stream.append(&acc.info.code_hash.0.as_ref()); - stream.out().freeze() +impl TrieAccount { + #[inline(always)] + fn new(acc: &PlainAccount) -> Self { + Self { + nonce: acc.info.nonce, + balance: acc.info.balance, + root_hash: sec_trie_root::( + acc.storage + .iter() + .filter(|(_k, &v)| v != U256::ZERO) + .map(|(k, v)| (k.to_be_bytes::<32>(), alloy_rlp::encode_fixed_size(v))), + ), + code_hash: acc.info.code_hash, + } + } } -pub fn trie_root(acc_data: Vec<(H160, Bytes)>) -> B256 { - B256(sec_trie_root::(acc_data).0) +#[inline] +pub fn trie_root(input: I) -> B256 +where + I: IntoIterator, + A: AsRef<[u8]>, + B: AsRef<[u8]>, +{ + sec_trie_root::(input) } #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct KeccakHasher; impl Hasher for KeccakHasher { - type Out = H256; + type Out = B256; type StdHasher = PlainHasher; const LENGTH: usize = 32; + + #[inline] fn hash(x: &[u8]) -> Self::Out { - let out = Keccak256::digest(x); - H256::from_slice(out.as_slice()) + keccak256(x) } } diff --git a/bins/revme/src/statetest/models/deserializer.rs b/bins/revme/src/statetest/models/deserializer.rs index a10bae0bc3..a89c70a99c 100644 --- a/bins/revme/src/statetest/models/deserializer.rs +++ b/bins/revme/src/statetest/models/deserializer.rs @@ -1,11 +1,5 @@ -use std::str::FromStr; - -use bytes::Bytes; -use revm::primitives::{B160, U256}; -use serde::{ - de::{self, Error}, - Deserialize, -}; +use revm::primitives::Address; +use serde::{de, Deserialize}; pub fn deserialize_str_as_u64<'de, D>(deserializer: D) -> Result where @@ -13,71 +7,22 @@ where { let string = String::deserialize(deserializer)?; - let output = if let Some(stripped) = string.strip_prefix("0x") { - u64::from_str_radix(stripped, 16).unwrap() + if let Some(stripped) = string.strip_prefix("0x") { + u64::from_str_radix(stripped, 16) } else { - string.parse().unwrap() - }; - - Ok(output) -} - -pub fn deserialize_str_as_u256<'de, D>(deserializer: D) -> Result -where - D: de::Deserializer<'de>, -{ - let string = String::deserialize(deserializer)?; - let output = string.parse().unwrap(); - - Ok(output) -} - -pub fn deserialize_vec_as_vec_bytes<'de, D>(deserializer: D) -> Result, D::Error> -where - D: de::Deserializer<'de>, -{ - let strings: Vec = Vec::::deserialize(deserializer)?; - - let mut out = Vec::new(); - for string in strings { - out.push( - hex::decode(string.strip_prefix("0x").unwrap_or(&string)) - .map_err(D::Error::custom)? - .into(), - ) + string.parse() } - Ok(out) + .map_err(serde::de::Error::custom) } -pub fn deserialize_maybe_empty<'de, D>(deserializer: D) -> Result, D::Error> +pub fn deserialize_maybe_empty<'de, D>(deserializer: D) -> Result, D::Error> where D: de::Deserializer<'de>, { - let string: String = String::deserialize(deserializer)?; + let string = String::deserialize(deserializer)?; if string.is_empty() { - return Ok(None); + Ok(None) + } else { + string.parse().map_err(de::Error::custom).map(Some) } - Ok(Some(B160::from_str(&string).map_err(D::Error::custom)?)) -} - -pub fn deserialize_str_as_bytes<'de, D>(deserializer: D) -> Result -where - D: de::Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - - Ok(hex::decode(s.strip_prefix("0x").unwrap_or(&s)) - .map_err(D::Error::custom)? - .into()) -} - -pub fn deserialize_opt_str_as_bytes<'de, D>(deserializer: D) -> Result, D::Error> -where - D: de::Deserializer<'de>, -{ - #[derive(Debug, Deserialize)] - struct WrappedValue(#[serde(deserialize_with = "deserialize_str_as_bytes")] Bytes); - - Option::::deserialize(deserializer) - .map(|opt_wrapped: Option| opt_wrapped.map(|wrapped: WrappedValue| wrapped.0)) } diff --git a/bins/revme/src/statetest/models/mod.rs b/bins/revme/src/statetest/models/mod.rs index 2f63099e95..24c12f10d3 100644 --- a/bins/revme/src/statetest/models/mod.rs +++ b/bins/revme/src/statetest/models/mod.rs @@ -1,5 +1,4 @@ -use bytes::Bytes; -use revm::primitives::{HashMap, B160, B256, U256}; +use revm::primitives::{Address, Bytes, HashMap, B256, U256}; use serde::Deserialize; use std::collections::BTreeMap; @@ -19,7 +18,7 @@ pub struct TestUnit { pub info: serde_json::Value, pub env: Env, - pub pre: HashMap, + pub pre: HashMap, pub post: BTreeMap>, pub transaction: TransactionParts, } @@ -32,18 +31,16 @@ pub struct Test { /// Indexes pub indexes: TxPartIndices, - /// Post state hash pub hash: B256, /// Post state #[serde(default)] - pub post_state: HashMap, + pub post_state: HashMap, /// Logs root pub logs: B256, /// Tx bytes - #[serde(default, deserialize_with = "deserialize_opt_str_as_bytes")] pub txbytes: Option, } @@ -59,7 +56,6 @@ pub struct TxPartIndices { #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct AccountInfo { pub balance: U256, - #[serde(deserialize_with = "deserialize_str_as_bytes")] pub code: Bytes, #[serde(deserialize_with = "deserialize_str_as_u64")] pub nonce: u64, @@ -69,14 +65,10 @@ pub struct AccountInfo { #[derive(Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Env { - pub current_coinbase: B160, - #[serde(default, deserialize_with = "deserialize_str_as_u256")] + pub current_coinbase: Address, pub current_difficulty: U256, - #[serde(deserialize_with = "deserialize_str_as_u256")] pub current_gas_limit: U256, - #[serde(deserialize_with = "deserialize_str_as_u256")] pub current_number: U256, - #[serde(deserialize_with = "deserialize_str_as_u256")] pub current_timestamp: U256, pub current_base_fee: Option, pub previous_hash: B256, @@ -92,15 +84,14 @@ pub struct Env { #[derive(Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct TransactionParts { - #[serde(deserialize_with = "deserialize_vec_as_vec_bytes")] pub data: Vec, pub gas_limit: Vec, pub gas_price: Option, pub nonce: U256, pub secret_key: B256, - pub sender: B160, + pub sender: Address, #[serde(deserialize_with = "deserialize_maybe_empty")] - pub to: Option, + pub to: Option
, pub value: Vec, pub max_fee_per_gas: Option, pub max_priority_fee_per_gas: Option, @@ -116,7 +107,7 @@ pub struct TransactionParts { #[derive(Debug, PartialEq, Eq, Deserialize, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct AccessListItem { - pub address: B160, + pub address: Address, pub storage_keys: Vec, } @@ -126,7 +117,7 @@ pub type AccessList = Vec; mod tests { use super::*; - use revm::primitives::B160; + use revm::primitives::Address; use serde_json::Error; #[test] @@ -149,7 +140,7 @@ mod tests { #[derive(Deserialize, Debug)] pub struct Test { - _item: B160, + _item: Address, } let out: Test = serde_json::from_str(json)?; diff --git a/bins/revme/src/statetest/runner.rs b/bins/revme/src/statetest/runner.rs index 476ad263e9..a898740d40 100644 --- a/bins/revme/src/statetest/runner.rs +++ b/bins/revme/src/statetest/runner.rs @@ -2,14 +2,13 @@ use super::{ merkle_trie::{log_rlp_hash, state_merkle_trie_root}, models::{SpecName, TestSuite}, }; -use hex_literal::hex; use indicatif::ProgressBar; use revm::{ inspectors::TracerEip3155, interpreter::CreateScheme, primitives::{ - calc_excess_blob_gas, keccak256, Bytecode, Env, HashMap, SpecId, TransactTo, B160, B256, - U256, + address, b256, calc_excess_blob_gas, keccak256, Bytecode, Env, HashMap, SpecId, TransactTo, + B256, U256, }, }; use std::{ @@ -120,40 +119,28 @@ pub fn execute_test_suite( let map_caller_keys: HashMap<_, _> = [ ( - B256(hex!( - "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - )), - B160(hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")), + b256!("45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"), + address!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b"), ), ( - B256(hex!( - "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4" - )), - B160(hex!("cd2a3d9f938e13cd947ec05abc7fe734df8dd826")), + b256!("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4"), + address!("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), ), ( - B256(hex!( - "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d" - )), - B160(hex!("82a978b3f5962a5b0957d9ee9eef472ee55b42f1")), + b256!("044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"), + address!("82a978b3f5962a5b0957d9ee9eef472ee55b42f1"), ), ( - B256(hex!( - "6a7eeac5f12b409d42028f66b0b2132535ee158cfda439e3bfdd4558e8f4bf6c" - )), - B160(hex!("c9c5a15a403e41498b6f69f6f89dd9f5892d21f7")), + b256!("6a7eeac5f12b409d42028f66b0b2132535ee158cfda439e3bfdd4558e8f4bf6c"), + address!("c9c5a15a403e41498b6f69f6f89dd9f5892d21f7"), ), ( - B256(hex!( - "a95defe70ebea7804f9c3be42d20d24375e2a92b9d9666b832069c5f3cd423dd" - )), - B160(hex!("3fb1cd2cd96c6d5c0b5eb3322d807b34482481d4")), + b256!("a95defe70ebea7804f9c3be42d20d24375e2a92b9d9666b832069c5f3cd423dd"), + address!("3fb1cd2cd96c6d5c0b5eb3322d807b34482481d4"), ), ( - B256(hex!( - "fe13266ff57000135fb9aa854bbfe455d8da85b21f626307bf3263a0c2a8e7fe" - )), - B160(hex!("dcc5ba93a1ed7e045690d722f2bf460a51c61415")), + b256!("fe13266ff57000135fb9aa854bbfe455d8da85b21f626307bf3263a0c2a8e7fe"), + address!("dcc5ba93a1ed7e045690d722f2bf460a51c61415"), ), ] .into(); @@ -227,16 +214,15 @@ pub fn execute_test_suite( env.cfg.spec_id = spec_name.to_spec_id(); for (index, test) in tests.into_iter().enumerate() { - let gas_limit = *unit.transaction.gas_limit.get(test.indexes.gas).unwrap(); - let gas_limit = u64::try_from(gas_limit).unwrap_or(u64::MAX); - env.tx.gas_limit = gas_limit; + env.tx.gas_limit = unit.transaction.gas_limit[test.indexes.gas].saturating_to(); + env.tx.data = unit .transaction .data .get(test.indexes.data) .unwrap() .clone(); - env.tx.value = *unit.transaction.value.get(test.indexes.value).unwrap(); + env.tx.value = unit.transaction.value[test.indexes.value]; env.tx.access_list = unit .transaction @@ -314,7 +300,7 @@ pub fn execute_test_suite( } let logs_root = - log_rlp_hash(exec_result.as_ref().map(|r| r.logs()).unwrap_or_default()); + log_rlp_hash(&exec_result.as_ref().map(|r| r.logs()).unwrap_or_default()); if logs_root != test.logs { return Err(TestError { diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 202025eb31..4344260156 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Dragan Rakita "] -description = "REVM Interpreter" +description = "revm Interpreter" edition = "2021" keywords = ["no_std", "ethereum", "evm", "revm", "interpreter"] license = "MIT" @@ -12,35 +12,14 @@ readme = "../../README.md" [dependencies] revm-primitives = { path = "../primitives", version = "1.2.0", default-features = false } -#utility -derive_more = "0.99" -enumn = "0.1" - -# sha3 keccak hasher -sha3 = { version = "0.10", default-features = false, features = [] } - # optional serde = { version = "1.0", features = ["derive", "rc"], optional = true } -arbitrary = { version = "1.3", features = ["derive"], optional = true } -proptest = { version = "1.3", optional = true } -proptest-derive = { version = "0.4", optional = true } - -[dev-dependencies] -arbitrary = { version = "1.3", features = ["derive"] } -proptest = "1.3" -proptest-derive = "0.4" [features] default = ["std"] std = ["revm-primitives/std"] serde = ["dep:serde", "revm-primitives/serde"] -arbitrary = [ - "std", - "dep:arbitrary", - "dep:proptest", - "dep:proptest-derive", - "revm-primitives/arbitrary", -] +arbitrary = ["std", "revm-primitives/arbitrary"] optimism = ["revm-primitives/optimism"] diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 2208c0b7c2..118775ee9f 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,6 +1,6 @@ use super::constants::*; use crate::inner_models::SelfDestructResult; -use crate::primitives::{Spec, SpecId::*, B160, U256}; +use crate::primitives::{Address, Spec, SpecId::*, U256}; use alloc::vec::Vec; #[allow(clippy::collapsible_else_if)] @@ -344,7 +344,7 @@ pub fn memory_gas(a: usize) -> u64 { pub fn initial_tx_gas( input: &[u8], is_create: bool, - access_list: &[(B160, Vec)], + access_list: &[(Address, Vec)], ) -> u64 { let mut initial_gas = 0; let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 777a84957e..57afa405aa 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -1,6 +1,6 @@ use crate::primitives::Bytecode; use crate::{ - primitives::{Bytes, Env, B160, B256, U256}, + primitives::{Address, Bytes, Env, B256, U256}, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, SelfDestructResult, }; use alloc::vec::Vec; @@ -20,38 +20,38 @@ pub trait Host { fn env(&mut self) -> &mut Env; /// load account. Returns (is_cold,is_new_account) - fn load_account(&mut self, address: B160) -> Option<(bool, bool)>; + fn load_account(&mut self, address: Address) -> Option<(bool, bool)>; /// Get environmental block hash. fn block_hash(&mut self, number: U256) -> Option; /// Get balance of address and if account is cold loaded. - fn balance(&mut self, address: B160) -> Option<(U256, bool)>; + fn balance(&mut self, address: Address) -> Option<(U256, bool)>; /// Get code of address and if account is cold loaded. - fn code(&mut self, address: B160) -> Option<(Bytecode, bool)>; + fn code(&mut self, address: Address) -> Option<(Bytecode, bool)>; /// Get code hash of address and if account is cold loaded. - fn code_hash(&mut self, address: B160) -> Option<(B256, bool)>; + fn code_hash(&mut self, address: Address) -> Option<(B256, bool)>; /// Get storage value of address at index and if account is cold loaded. - fn sload(&mut self, address: B160, index: U256) -> Option<(U256, bool)>; + fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)>; /// Set storage value of account address at index. /// Returns (original, present, new, sis_cold) fn sstore( &mut self, - address: B160, + address: Address, index: U256, value: U256, ) -> Option<(U256, U256, U256, bool)>; /// Get the transient storage value of address at index. - fn tload(&mut self, address: B160, index: U256) -> U256; + fn tload(&mut self, address: Address, index: U256) -> U256; /// Set the transient storage value of address at index. - fn tstore(&mut self, address: B160, index: U256, value: U256); + fn tstore(&mut self, address: Address, index: U256, value: U256); /// Create a log owned by address with given topics and data. - fn log(&mut self, address: B160, topics: Vec, data: Bytes); + fn log(&mut self, address: Address, topics: Vec, data: Bytes); /// Mark an address to be deleted, with funds transferred to target. - fn selfdestruct(&mut self, address: B160, target: B160) -> Option; + fn selfdestruct(&mut self, address: Address, target: Address) -> Option; /// Invoke a create operation. fn create( &mut self, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes); + ) -> (InstructionResult, Option
, Gas, Bytes); /// Invoke a call operation. fn call(&mut self, input: &mut CallInputs) -> (InstructionResult, Gas, Bytes); } diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 394bd26fe2..72b7699da2 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,6 +1,6 @@ use crate::primitives::{hash_map::Entry, Bytecode, Bytes, HashMap, U256}; use crate::{ - primitives::{Env, Log, B160, B256, KECCAK_EMPTY}, + primitives::{Address, Env, Log, B256, KECCAK_EMPTY}, CallInputs, CreateInputs, Gas, Host, InstructionResult, Interpreter, SelfDestructResult, }; use alloc::vec::Vec; @@ -53,32 +53,32 @@ impl Host for DummyHost { } #[inline] - fn load_account(&mut self, _address: B160) -> Option<(bool, bool)> { + fn load_account(&mut self, _address: Address) -> Option<(bool, bool)> { Some((true, true)) } #[inline] fn block_hash(&mut self, _number: U256) -> Option { - Some(B256::zero()) + Some(B256::ZERO) } #[inline] - fn balance(&mut self, _address: B160) -> Option<(U256, bool)> { + fn balance(&mut self, _address: Address) -> Option<(U256, bool)> { Some((U256::ZERO, false)) } #[inline] - fn code(&mut self, _address: B160) -> Option<(Bytecode, bool)> { + fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> { Some((Bytecode::default(), false)) } #[inline] - fn code_hash(&mut self, __address: B160) -> Option<(B256, bool)> { + fn code_hash(&mut self, __address: Address) -> Option<(B256, bool)> { Some((KECCAK_EMPTY, false)) } #[inline] - fn sload(&mut self, __address: B160, index: U256) -> Option<(U256, bool)> { + fn sload(&mut self, __address: Address, index: U256) -> Option<(U256, bool)> { match self.storage.entry(index) { Entry::Occupied(entry) => Some((*entry.get(), false)), Entry::Vacant(entry) => { @@ -91,7 +91,7 @@ impl Host for DummyHost { #[inline] fn sstore( &mut self, - _address: B160, + _address: Address, index: U256, value: U256, ) -> Option<(U256, U256, U256, bool)> { @@ -107,7 +107,7 @@ impl Host for DummyHost { } #[inline] - fn tload(&mut self, _address: B160, index: U256) -> U256 { + fn tload(&mut self, _address: Address, index: U256) -> U256 { self.transient_storage .get(&index) .copied() @@ -115,12 +115,12 @@ impl Host for DummyHost { } #[inline] - fn tstore(&mut self, _address: B160, index: U256, value: U256) { + fn tstore(&mut self, _address: Address, index: U256, value: U256) { self.transient_storage.insert(index, value); } #[inline] - fn log(&mut self, address: B160, topics: Vec, data: Bytes) { + fn log(&mut self, address: Address, topics: Vec, data: Bytes) { self.log.push(Log { address, topics, @@ -129,7 +129,7 @@ impl Host for DummyHost { } #[inline] - fn selfdestruct(&mut self, _address: B160, _target: B160) -> Option { + fn selfdestruct(&mut self, _address: Address, _target: Address) -> Option { panic!("Selfdestruct is not supported for this host") } @@ -137,7 +137,7 @@ impl Host for DummyHost { fn create( &mut self, _inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { panic!("Create is not supported for this host") } diff --git a/crates/interpreter/src/inner_models.rs b/crates/interpreter/src/inner_models.rs index 5467876995..614ea567d0 100644 --- a/crates/interpreter/src/inner_models.rs +++ b/crates/interpreter/src/inner_models.rs @@ -1,18 +1,14 @@ pub use crate::primitives::CreateScheme; -use crate::primitives::{Bytes, B160, U256}; +use crate::primitives::{Address, Bytes, U256}; /// Inputs for a call. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CallInputs { /// The target of the call. - pub contract: B160, + pub contract: Address, /// The transfer, if any, in this call. pub transfer: Transfer, /// The call data of the call. - #[cfg_attr( - feature = "serde", - serde(with = "crate::primitives::utilities::serde_hex_bytes") - )] pub input: Bytes, /// The gas limit of the call. pub gas_limit: u64, @@ -24,13 +20,9 @@ pub struct CallInputs { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateInputs { - pub caller: B160, + pub caller: Address, pub scheme: CreateScheme, pub value: U256, - #[cfg_attr( - feature = "serde", - serde(with = "crate::primitives::utilities::serde_hex_bytes") - )] pub init_code: Bytes, pub gas_limit: u64, } @@ -54,11 +46,11 @@ pub enum CallScheme { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CallContext { /// Execution address. - pub address: B160, + pub address: Address, /// Caller of the EVM. - pub caller: B160, + pub caller: Address, /// The address the contract code was loaded from, if any. - pub code_address: B160, + pub code_address: Address, /// Apparent value of the EVM. pub apparent_value: U256, /// The scheme used for the call. @@ -68,9 +60,9 @@ pub struct CallContext { impl Default for CallContext { fn default() -> Self { CallContext { - address: B160::default(), - caller: B160::default(), - code_address: B160::default(), + address: Address::default(), + caller: Address::default(), + code_address: Address::default(), apparent_value: U256::default(), scheme: CallScheme::Call, } @@ -82,9 +74,9 @@ impl Default for CallContext { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Transfer { /// Source address. - pub source: B160, + pub source: Address, /// Target address. - pub target: B160, + pub target: Address, /// Transfer value. pub value: U256, } diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 51d2b57a21..babeba926c 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -1,9 +1,10 @@ +use crate::primitives::{Address, Bytes, Spec, SpecId::*, B256, U256}; +use crate::MAX_INITCODE_SIZE; use crate::{ gas::{self, COLD_ACCOUNT_ACCESS_COST, WARM_STORAGE_READ_COST}, interpreter::Interpreter, - primitives::{Bytes, Spec, SpecId::*, B160, B256, U256}, return_ok, return_revert, CallContext, CallInputs, CallScheme, CreateInputs, CreateScheme, - Host, InstructionResult, Transfer, MAX_INITCODE_SIZE, + Host, InstructionResult, Transfer, }; use alloc::{boxed::Box, vec::Vec}; use core::cmp::min; @@ -208,7 +209,7 @@ pub fn log(interpreter: &mut Interpreter, host: &mut H) let mut topics = Vec::with_capacity(N); for _ in 0..N { // Safety: stack bounds already checked few lines above - topics.push(B256(unsafe { + topics.push(B256::new(unsafe { interpreter.stack.pop_unsafe().to_be_bytes() })); } @@ -325,14 +326,16 @@ pub fn create( match return_reason { return_ok!() => { - push_b256!(interpreter, address.map_or(B256::zero(), |a| a.into())); + push_b256!(interpreter, address.unwrap_or_default().into_word()); + if crate::USE_GAS { interpreter.gas.erase_cost(gas.remaining()); interpreter.gas.record_refund(gas.refunded()); } } return_revert!() => { - push!(interpreter, U256::ZERO); + push_b256!(interpreter, B256::ZERO); + if crate::USE_GAS { interpreter.gas.erase_cost(gas.remaining()); } @@ -340,7 +343,9 @@ pub fn create( InstructionResult::FatalExternalError => { interpreter.instruction_result = InstructionResult::FatalExternalError; } - _ => push!(interpreter, U256::ZERO), + _ => { + push_b256!(interpreter, B256::ZERO); + } } } diff --git a/crates/interpreter/src/instructions/host_env.rs b/crates/interpreter/src/instructions/host_env.rs index 98a4a110df..cce993bac6 100644 --- a/crates/interpreter/src/instructions/host_env.rs +++ b/crates/interpreter/src/instructions/host_env.rs @@ -13,7 +13,7 @@ pub fn chainid(interpreter: &mut Interpreter, host: &mut H) pub fn coinbase(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push_b256!(interpreter, host.env().block.coinbase.into()); + push_b256!(interpreter, host.env().block.coinbase.into_word()); } pub fn timestamp(interpreter: &mut Interpreter, host: &mut H) { @@ -54,7 +54,7 @@ pub fn basefee(interpreter: &mut Interpreter, host: &mut H) pub fn origin(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push_b256!(interpreter, host.env().tx.caller.into()); + push_b256!(interpreter, host.env().tx.caller.into_word()); } // EIP-4844: Shard Blob Transactions diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 052a4a830b..714a83368b 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -79,35 +79,22 @@ macro_rules! memory_resize { } macro_rules! pop_address { - ( $interp:expr, $x1:ident) => { + ($interp:expr, $x1:ident) => { if $interp.stack.len() < 1 { $interp.instruction_result = InstructionResult::StackUnderflow; return; } // Safety: Length is checked above. - let $x1: B160 = B160( - unsafe { $interp.stack.pop_unsafe() }.to_be_bytes::<{ U256::BYTES }>()[12..] - .try_into() - .unwrap(), - ); + let $x1 = Address::from_word(B256::from(unsafe { $interp.stack.pop_unsafe() })); }; - ( $interp:expr, $x1:ident, $x2:ident) => { + ($interp:expr, $x1:ident, $x2:ident) => { if $interp.stack.len() < 2 { $interp.instruction_result = InstructionResult::StackUnderflow; return; } - let mut temp = H256::zero(); - - let $x1: B160 = B160( - unsafe { $interp.stack.pop_unsafe() }.to_be_bytes::<{ U256::BYTES }>()[12..] - .try_into() - .unwrap(), - ); - let $x2: B160 = B160( - unsafe { $interp.stack.pop_unsafe() }.to_be_bytes::<{ U256::BYTES }>()[12..] - .try_into() - .unwrap(), - ); + // Safety: Length is checked above. + let $x1 = Address::from_word(B256::from(unsafe { $interp.stack.pop_unsafe() })); + let $x2 = Address::from_word(B256::from(unsafe { $interp.stack.pop_unsafe() })); }; } diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 3153bb664b..e4976058ed 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -21,12 +21,12 @@ pub fn keccak256(interpreter: &mut Interpreter, _host: &mut H) { pub fn address(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::BASE); - push_b256!(interpreter, B256::from(interpreter.contract.address)); + push_b256!(interpreter, interpreter.contract.address.into_word()); } pub fn caller(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::BASE); - push_b256!(interpreter, B256::from(interpreter.contract.caller)); + push_b256!(interpreter, interpreter.contract.caller.into_word()); } pub fn codesize(interpreter: &mut Interpreter, _host: &mut H) { @@ -58,19 +58,16 @@ pub fn calldataload(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); pop!(interpreter, index); let index = as_usize_saturated!(index); - let load = if index < interpreter.contract.input.len() { - let n = 32.min(interpreter.contract.input.len() - index); + let have_bytes = 32.min(interpreter.contract.input.len() - index); let mut bytes = [0u8; 32]; - // SAFETY: n <= len - index -> index + n <= len - let src = unsafe { interpreter.contract.input.get_unchecked(index..index + n) }; - bytes[..n].copy_from_slice(src); - U256::from_be_bytes(bytes) + bytes[..have_bytes].copy_from_slice(&interpreter.contract.input[index..index + have_bytes]); + B256::new(bytes) } else { - U256::ZERO + B256::ZERO }; - push!(interpreter, load); + push_b256!(interpreter, load); } pub fn calldatasize(interpreter: &mut Interpreter, _host: &mut H) { diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 1467b874cb..bc7a248097 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,5 +1,5 @@ use super::analysis::{to_analysed, BytecodeLocked}; -use crate::primitives::{Bytecode, Bytes, Env, TransactTo, B160, B256, U256}; +use crate::primitives::{Address, Bytecode, Bytes, Env, TransactTo, B256, U256}; use crate::CallContext; #[derive(Clone, Debug, Default)] @@ -12,9 +12,9 @@ pub struct Contract { /// Bytecode hash. pub hash: B256, /// Contract address - pub address: B160, + pub address: Address, /// Caller of the EVM. - pub caller: B160, + pub caller: Address, /// Value send to contract. pub value: U256, } @@ -26,8 +26,8 @@ impl Contract { input: Bytes, bytecode: Bytecode, hash: B256, - address: B160, - caller: B160, + address: Address, + caller: Address, value: U256, ) -> Self { let bytecode = to_analysed(bytecode).try_into().expect("it is analyzed"); @@ -47,7 +47,7 @@ impl Contract { pub fn new_env(env: &Env, bytecode: Bytecode, hash: B256) -> Self { let contract_address = match env.tx.transact_to { TransactTo::Call(caller) => caller, - TransactTo::Create(..) => B160::zero(), + TransactTo::Create(..) => Address::ZERO, }; Self::new( env.tx.data.clone(), diff --git a/crates/interpreter/src/interpreter/memory.rs b/crates/interpreter/src/interpreter/memory.rs index 9982cf6096..aa3a43fdb0 100644 --- a/crates/interpreter/src/interpreter/memory.rs +++ b/crates/interpreter/src/interpreter/memory.rs @@ -1,4 +1,5 @@ -use crate::{alloc::vec::Vec, primitives::U256}; +use crate::primitives::U256; +use alloc::vec::Vec; use core::{ cmp::min, fmt, diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 7ecbd729d2..a55265d791 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] +#![warn(unused_crate_dependencies)] extern crate alloc; diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index b5887d4571..1141f838a7 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 = "revm Precompiles - Ethereum compatible precompiled contracts" edition = "2021" keywords = ["no_std", "ethereum", "evm", "revm", "precompiles"] license = "MIT" @@ -14,23 +14,20 @@ exclude = ["build.rs", "src/blob/kzg_settings/*.txt"] [dependencies] revm-primitives = { path = "../primitives", version = "1.2.0", default-features = false } bn = { package = "substrate-bn", version = "0.6", default-features = false } -k256 = { version = "0.13", default-features = false, features = ["ecdsa"] } num = { version = "0.4.0", default-features = false, features = ["alloc"] } once_cell = { version = "1.17", default-features = false, features = ["alloc"] } ripemd = { version = "0.1", default-features = false } +sha2 = { version = "0.10", default-features = false } + +# Optional KZG point evaluation precompile +c-kzg = { version = "0.1.1", default-features = false, optional = true } + +# ecRecover precompile +k256 = { version = "0.13", default-features = false, features = ["ecdsa"] } secp256k1 = { version = "0.27.0", default-features = false, features = [ "alloc", "recovery", ], optional = true } -sha2 = { version = "0.10.8", default-features = false } -sha3 = { version = "0.10.7", default-features = false } -c-kzg = { version="0.1.1", default-features = false, optional = true } - -[dev-dependencies] -hex = "0.4" - -[build-dependencies] -hex = "0.4" [features] default = ["std", "c-kzg", "secp256k1"] @@ -41,17 +38,18 @@ std = [ "once_cell/std", "ripemd/std", "sha2/std", - "sha3/std", "c-kzg?/std", "secp256k1?/std", ] -# The following features may not work on all platforms as they depend on C libraries. +optimism = ["revm-primitives/optimism"] + + +# This library may not work on all no_std platforms as they depend on C libraries. + # Enables the KZG point evaluation precompile. c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg"] - # Use `secp256k1` as a faster alternative to `k256`. # The problem that `secp256k1` has is it fails to build for `wasm` target on Windows and Mac as it is c lib. # In Linux it passes. If you don't require to build wasm on win/mac, it is safe to use it and it is enabled by default. secp256k1 = ["dep:secp256k1"] -optimism = ["revm-primitives/optimism"] diff --git a/crates/precompile/src/blake2.rs b/crates/precompile/src/blake2.rs index 803c644549..80d78a9bf9 100644 --- a/crates/precompile/src/blake2.rs +++ b/crates/precompile/src/blake2.rs @@ -6,7 +6,7 @@ const F_ROUND: u64 = 1; const INPUT_LENGTH: usize = 213; pub const FUN: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(9), + crate::u64_to_address(9), Precompile::Standard(run as StandardPrecompileFn), ); diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index 8d82a01db7..914817cc01 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -1,9 +1,9 @@ -use crate::{primitives::U256, Error, Precompile, PrecompileAddress, PrecompileResult, B160}; +use crate::{primitives::U256, Address, Error, Precompile, PrecompileAddress, PrecompileResult}; use alloc::vec::Vec; pub mod add { use super::*; - const ADDRESS: B160 = crate::u64_to_b160(6); + const ADDRESS: Address = crate::u64_to_address(6); pub const ISTANBUL: PrecompileAddress = PrecompileAddress( ADDRESS, @@ -28,7 +28,7 @@ pub mod add { pub mod mul { use super::*; - const ADDRESS: B160 = crate::u64_to_b160(7); + const ADDRESS: Address = crate::u64_to_address(7); pub const ISTANBUL: PrecompileAddress = PrecompileAddress( ADDRESS, Precompile::Standard(|input: &[u8], gas_limit: u64| -> PrecompileResult { @@ -52,7 +52,7 @@ pub mod mul { pub mod pair { use super::*; - const ADDRESS: B160 = crate::u64_to_b160(8); + const ADDRESS: Address = crate::u64_to_address(8); const ISTANBUL_PAIR_PER_POINT: u64 = 34_000; const ISTANBUL_PAIR_BASE: u64 = 45_000; diff --git a/crates/precompile/src/hash.rs b/crates/precompile/src/hash.rs index b5b231d660..c750507f78 100644 --- a/crates/precompile/src/hash.rs +++ b/crates/precompile/src/hash.rs @@ -3,11 +3,11 @@ use crate::{Error, Precompile, PrecompileAddress, PrecompileResult, StandardPrec use sha2::*; pub const SHA256: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(2), + crate::u64_to_address(2), Precompile::Standard(sha256_run as StandardPrecompileFn), ); pub const RIPEMD160: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(3), + crate::u64_to_address(3), Precompile::Standard(ripemd160_run as StandardPrecompileFn), ); diff --git a/crates/precompile/src/identity.rs b/crates/precompile/src/identity.rs index 9dda458792..7f54931a17 100644 --- a/crates/precompile/src/identity.rs +++ b/crates/precompile/src/identity.rs @@ -2,7 +2,7 @@ use super::calc_linear_cost_u32; use crate::{Error, Precompile, PrecompileAddress, PrecompileResult, StandardPrecompileFn}; pub const FUN: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(4), + crate::u64_to_address(4), Precompile::Standard(identity_run as StandardPrecompileFn), ); diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index b4968c9bc9..579f2333b5 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -1,13 +1,13 @@ -use crate::{Error, Precompile, PrecompileAddress, PrecompileResult, B160}; +use crate::{Address, Error, Precompile, PrecompileAddress, PrecompileResult}; use c_kzg::{Bytes32, Bytes48, KzgProof, KzgSettings}; use revm_primitives::{hex_literal::hex, Env}; use sha2::{Digest, Sha256}; pub const POINT_EVALUATION: PrecompileAddress = PrecompileAddress(ADDRESS, Precompile::Env(run)); -pub const ADDRESS: B160 = crate::u64_to_b160(0x0A); -pub const GAS_COST: u64 = 50_000; -pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; +const ADDRESS: Address = crate::u64_to_address(0x0A); +const GAS_COST: u64 = 50_000; +const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; /// `U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes() ++ BLS_MODULUS.to_bytes32()` const RETURN_VALUE: &[u8; 64] = &hex!( diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index feecb34bfa..36c3d88f9c 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -1,4 +1,5 @@ #![no_std] +#![warn(unused_crate_dependencies)] #[macro_use] extern crate alloc; @@ -22,7 +23,7 @@ pub use primitives::{ #[doc(inline)] pub use revm_primitives as primitives; -pub type B160 = [u8; 20]; +pub type Address = [u8; 20]; pub type B256 = [u8; 32]; pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { @@ -38,7 +39,7 @@ pub struct PrecompileOutput { #[derive(Debug, Default)] pub struct Log { - pub address: B160, + pub address: Address, pub topics: Vec, pub data: Bytes, } @@ -55,7 +56,7 @@ impl PrecompileOutput { #[derive(Clone, Debug)] pub struct Precompiles { - pub fun: HashMap, + pub fun: HashMap, } impl Default for Precompiles { @@ -79,9 +80,9 @@ impl fmt::Debug for Precompile { } } -pub struct PrecompileAddress(B160, Precompile); +pub struct PrecompileAddress(Address, Precompile); -impl From for (B160, Precompile) { +impl From for (Address, Precompile) { fn from(value: PrecompileAddress) -> Self { (value.0, value.1) } @@ -234,15 +235,15 @@ impl Precompiles { } } - pub fn addresses(&self) -> impl IntoIterator { + pub fn addresses(&self) -> impl IntoIterator { self.fun.keys() } - pub fn contains(&self, address: &B160) -> bool { + pub fn contains(&self, address: &Address) -> bool { self.fun.contains_key(address) } - pub fn get(&self, address: &B160) -> Option { + pub fn get(&self, address: &Address) -> Option { //return None; self.fun.get(address).cloned() } @@ -256,13 +257,14 @@ impl Precompiles { } } -/// const fn for making an address by concatenating the bytes from two given numbers, +/// Const function for making an address by concatenating the bytes from two given numbers. +/// /// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used /// as a convenience for specifying the addresses of the various precompiles. -const fn u64_to_b160(x: u64) -> B160 { - let x_bytes = x.to_be_bytes(); +#[inline] +const fn u64_to_address(x: u64) -> Address { + let x = x.to_be_bytes(); [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x_bytes[0], x_bytes[1], x_bytes[2], x_bytes[3], - x_bytes[4], x_bytes[5], x_bytes[6], x_bytes[7], + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], ] } diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index 6d47c8d53b..072c2c6fe9 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -9,12 +9,12 @@ use core::{ use num::{BigUint, One, Zero}; pub const BYZANTIUM: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(5), + crate::u64_to_address(5), Precompile::Standard(byzantium_run as StandardPrecompileFn), ); pub const BERLIN: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(5), + crate::u64_to_address(5), Precompile::Standard(berlin_run as StandardPrecompileFn), ); @@ -199,8 +199,8 @@ fn berlin_gas_calc(base_length: u64, exp_length: u64, mod_length: u64, exp_highp #[cfg(test)] mod tests { - use super::*; + use revm_primitives::hex; struct Test { input: &'static str, diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 7bd44d09d6..f2408a7846 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -1,17 +1,16 @@ use crate::{Error, Precompile, PrecompileAddress, PrecompileResult, StandardPrecompileFn}; pub const ECRECOVER: PrecompileAddress = PrecompileAddress( - crate::u64_to_b160(1), + crate::u64_to_address(1), Precompile::Standard(ec_recover_run as StandardPrecompileFn), ); #[cfg(not(feature = "secp256k1"))] #[allow(clippy::module_inception)] mod secp256k1 { - use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; - use sha3::{Digest, Keccak256}; - use crate::B256; + use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; + use revm_primitives::keccak256; pub fn ecrecover(sig: &[u8; 65], msg: &B256) -> Result { // parse signature @@ -22,15 +21,15 @@ mod secp256k1 { let recovered_key = VerifyingKey::recover_from_prehash(msg, &signature, recid)?; // hash it - let hash = Keccak256::digest( + let mut hash = keccak256( &recovered_key .to_encoded_point(/* compress = */ false) .as_bytes()[1..], - ); + ) + .0; // truncate to 20 bytes - let mut hash: B256 = hash[..].try_into().unwrap(); - hash.iter_mut().take(12).for_each(|i| *i = 0); + hash[..12].fill(0); Ok(hash) } } @@ -39,11 +38,14 @@ mod secp256k1 { #[allow(clippy::module_inception)] mod secp256k1 { use crate::B256; + use revm_primitives::keccak256; use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, Message, Secp256k1, }; - use sha3::{Digest, Keccak256}; + + // Silence the unused crate dependency warning. + use k256 as _; pub fn ecrecover(sig: &[u8; 65], msg: &B256) -> Result { let sig = @@ -52,9 +54,8 @@ mod secp256k1 { let secp = Secp256k1::new(); let public = secp.recover_ecdsa(&Message::from_slice(&msg[..32])?, &sig)?; - let hash = Keccak256::digest(&public.serialize_uncompressed()[1..]); - let mut hash: B256 = hash[..].try_into().unwrap(); - hash.iter_mut().take(12).for_each(|i| *i = 0); + let mut hash = keccak256(&public.serialize_uncompressed()[1..]).0; + hash[..12].fill(0); Ok(hash) } } diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 982b665907..f3cb770c29 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Dragan Rakita "] -description = "REVM primitives" +description = "revm primitives" edition = "2021" keywords = ["no_std", "ethereum", "evm", "revm", "types"] license = "MIT" @@ -10,78 +10,41 @@ version = "1.2.0" readme = "../../README.md" [dependencies] -bytes = { version = "1.5", default-features = false } -hashbrown = "0.14" -primitive-types = { version = "0.12", default-features = false } -rlp = { version = "0.5", default-features = false } # used for create2 address calculation -ruint = { version = "1.8.0", default-features = false, features = [ - "primitive-types", +alloy-primitives = { version = "0.4", default-features = false, features = [ "rlp", ] } +alloy-rlp = { version = "0.3", default-features = false, features = ["derive"] } +hashbrown = "0.14" auto_impl = "1.1" bitvec = { version = "1", default-features = false, features = ["alloc"] } bitflags = { version = "2.4.0", default-features = false } -# For setting the CfgEnv KZGSettings. Enabled by std flag. +# For setting the CfgEnv KZGSettings. Enabled by c-kzg flag. c-kzg = { version = "0.1.1", default-features = false, optional = true } +once_cell = { version = "1.18", default-features = false, optional = true } -# bits B256 B160 crate -fixed-hash = { version = "0.8", default-features = false, features = [ - "rustc-hex", -] } - -#utility -hex-literal = "0.4" -hex = { version = "0.4", default-features = false, features = ["alloc"] } -derive_more = "0.99" +# utility enumn = "0.1" -once_cell = { version = "1.18", default-features = false } - -# sha3 keccak hasher -sha3 = { version = "0.10", default-features = false } # optional serde = { version = "1.0", features = ["derive", "rc"], optional = true } -arbitrary = { version = "1.3", features = ["derive"], optional = true } -proptest = { version = "1.3", optional = true } -proptest-derive = { version = "0.4", optional = true } - -[dev-dependencies] -arbitrary = { version = "1.3", features = ["derive"] } -proptest = "1.3" -proptest-derive = "0.4" -ruint = { version = "1.10.1", features = [ - "primitive-types", - "rlp", - "proptest", - "arbitrary", -] } [build-dependencies] hex = "0.4" [features] default = ["std", "c-kzg"] -std = ["bytes/std", "rlp/std", "hex/std", "bitvec/std", "bitflags/std"] +std = ["alloy-rlp/std", "hex/std", "bitvec/std", "bitflags/std"] serde = [ "dep:serde", + "alloy-primitives/serde", "hex/serde", "hashbrown/serde", - "ruint/serde", - "bytes/serde", "bitvec/serde", "bitflags/serde", "c-kzg?/serde", ] -arbitrary = [ - "std", - "ruint/arbitrary", - "ruint/proptest", - "dep:arbitrary", - "dep:proptest", - "dep:proptest-derive", - "bitflags/arbitrary", -] +arbitrary = ["std", "alloy-primitives/arbitrary", "bitflags/arbitrary"] optimism = [] @@ -102,4 +65,4 @@ optional_gas_refund = [] optional_no_base_fee = [] # See comments in `revm-precompile` -c-kzg = ["dep:c-kzg"] +c-kzg = ["dep:c-kzg", "dep:once_cell"] diff --git a/crates/primitives/src/bits.rs b/crates/primitives/src/bits.rs deleted file mode 100644 index 440c3029ee..0000000000 --- a/crates/primitives/src/bits.rs +++ /dev/null @@ -1,378 +0,0 @@ -#![allow(clippy::non_canonical_clone_impl)] - -use derive_more::{AsRef, Deref}; -use fixed_hash::{construct_fixed_hash, impl_fixed_hash_conversions}; - -#[cfg(any(test, feature = "arbitrary"))] -use arbitrary::Arbitrary; -#[cfg(any(test, feature = "arbitrary"))] -use proptest_derive::Arbitrary as PropTestArbitrary; - -construct_fixed_hash! { - /// revm 256 bits type. - #[cfg_attr(any(test, feature = "arbitrary"), derive(Arbitrary, PropTestArbitrary))] - #[derive(AsRef,Deref)] - pub struct B256(32); -} - -construct_fixed_hash! { - /// revm 160 bits type. - #[cfg_attr(any(test, feature = "arbitrary"), derive(Arbitrary, PropTestArbitrary))] - #[derive(AsRef,Deref)] - pub struct B160(20); -} - -impl From for B160 { - fn from(fr: u64) -> Self { - let x_bytes = fr.to_be_bytes(); - B160([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x_bytes[0], x_bytes[1], x_bytes[2], x_bytes[3], - x_bytes[4], x_bytes[5], x_bytes[6], x_bytes[7], - ]) - } -} - -impl From for B160 { - fn from(fr: primitive_types::H160) -> Self { - B160(fr.0) - } -} - -impl From for B256 { - fn from(fr: primitive_types::H256) -> Self { - B256(fr.0) - } -} - -impl From for primitive_types::H160 { - fn from(fr: B160) -> Self { - primitive_types::H160(fr.0) - } -} - -impl From for primitive_types::H256 { - fn from(fr: B256) -> Self { - primitive_types::H256(fr.0) - } -} - -impl From for B256 { - fn from(fr: primitive_types::U256) -> Self { - let mut ret = B256::zero(); - fr.to_big_endian(ret.as_bytes_mut()); - ret - } -} - -impl From for primitive_types::U256 { - fn from(fr: B256) -> Self { - primitive_types::U256::from(fr.as_ref() as &[u8]) - } -} - -impl From for B256 { - fn from(fr: ruint::aliases::U256) -> Self { - B256(fr.to_be_bytes()) - } -} - -impl From for ruint::aliases::U256 { - fn from(fr: B256) -> Self { - ruint::aliases::U256::from_be_bytes(fr.0) - } -} - -impl_fixed_hash_conversions!(B256, B160); - -#[cfg(feature = "serde")] -impl serde::Serialize for B256 { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut slice = [0u8; 2 + 2 * 32]; - serialize::serialize_raw(&mut slice, &self.0, serializer) - } -} -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for B256 { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let mut bytes = [0u8; 32]; - serialize::deserialize_check_len(deserializer, serialize::ExpectedLen::Exact(&mut bytes))?; - Ok(B256(bytes)) - } -} -#[cfg(feature = "serde")] -impl serde::Serialize for B160 { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut slice = [0u8; 2 + 2 * 20]; - serialize::serialize_raw(&mut slice, &self.0, serializer) - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for B160 { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let mut bytes = [0u8; 20]; - serialize::deserialize_check_len(deserializer, serialize::ExpectedLen::Exact(&mut bytes))?; - Ok(B160(bytes)) - } -} - -// code optained from: https://docs.rs/impl-serde/0.4.0/impl_serde/ -#[cfg(feature = "serde")] -mod serialize { - - use alloc::string::String; - use core::{fmt, result::Result}; - use serde::{de, Deserializer, Serializer}; - - static CHARS: &[u8] = b"0123456789abcdef"; - - fn to_hex_raw<'a>(v: &'a mut [u8], bytes: &[u8], skip_leading_zero: bool) -> &'a str { - assert!(v.len() > 1 + bytes.len() * 2); - - v[0] = b'0'; - v[1] = b'x'; - - let mut idx = 2; - let first_nibble = bytes[0] >> 4; - if first_nibble != 0 || !skip_leading_zero { - v[idx] = CHARS[first_nibble as usize]; - idx += 1; - } - v[idx] = CHARS[(bytes[0] & 0xf) as usize]; - idx += 1; - - for &byte in bytes.iter().skip(1) { - v[idx] = CHARS[(byte >> 4) as usize]; - v[idx + 1] = CHARS[(byte & 0xf) as usize]; - idx += 2; - } - - // SAFETY: all characters come either from CHARS or "0x", therefore valid UTF8 - unsafe { core::str::from_utf8_unchecked(&v[0..idx]) } - } - - /// Decoding bytes from hex string error. - #[derive(Debug, PartialEq, Eq)] - pub enum FromHexError { - /// Invalid (non-hex) character encountered. - InvalidHex { - /// The unexpected character. - character: char, - /// Index of that occurrence. - index: usize, - }, - } - - #[cfg(feature = "std")] - impl std::error::Error for FromHexError {} - - impl fmt::Display for FromHexError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - Self::InvalidHex { character, index } => { - write!(fmt, "invalid hex character: {character}, at {index}") - } - } - } - } - - /// Decode given 0x-prefix-stripped hex string into provided slice. - /// Used internally by `from_hex` and `deserialize_check_len`. - /// - /// The method will panic if `bytes` have incorrect length (make sure to allocate enough beforehand). - fn from_hex_raw(v: &str, bytes: &mut [u8], stripped: bool) -> Result { - let bytes_len = v.len(); - let mut modulus = bytes_len % 2; - let mut buf = 0; - let mut pos = 0; - for (index, byte) in v.bytes().enumerate() { - buf <<= 4; - - match byte { - b'A'..=b'F' => buf |= byte - b'A' + 10, - b'a'..=b'f' => buf |= byte - b'a' + 10, - b'0'..=b'9' => buf |= byte - b'0', - b' ' | b'\r' | b'\n' | b'\t' => { - buf >>= 4; - continue; - } - b => { - let character = char::from(b); - return Err(FromHexError::InvalidHex { - character, - index: index + if stripped { 2 } else { 0 }, - }); - } - } - - modulus += 1; - if modulus == 2 { - modulus = 0; - bytes[pos] = buf; - pos += 1; - } - } - - Ok(pos) - } - - /// Serializes a slice of bytes. - pub fn serialize_raw( - slice: &mut [u8], - bytes: &[u8], - serializer: S, - ) -> Result - where - S: Serializer, - { - if bytes.is_empty() { - serializer.serialize_str("0x") - } else { - serializer.serialize_str(to_hex_raw(slice, bytes, false)) - } - } - - /// Expected length of bytes vector. - #[derive(Debug, PartialEq, Eq)] - pub enum ExpectedLen<'a> { - /// Exact length in bytes. - Exact(&'a mut [u8]), - /// A bytes length between (min; slice.len()]. - #[allow(dead_code)] - Between(usize, &'a mut [u8]), - } - - impl<'a> fmt::Display for ExpectedLen<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExpectedLen::Exact(ref v) => write!(fmt, "length of {}", v.len() * 2), - ExpectedLen::Between(min, ref v) => { - write!(fmt, "length between ({}; {}]", min * 2, v.len() * 2) - } - } - } - } - - /// Deserialize into vector of bytes with additional size check. - /// Returns number of bytes written. - pub fn deserialize_check_len<'a, 'de, D>( - deserializer: D, - len: ExpectedLen<'a>, - ) -> Result - where - D: Deserializer<'de>, - { - struct Visitor<'a> { - len: ExpectedLen<'a>, - } - - impl<'a, 'b> de::Visitor<'b> for Visitor<'a> { - type Value = usize; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!( - formatter, - "a (both 0x-prefixed or not) hex string with {}", - self.len - ) - } - - fn visit_str(self, v: &str) -> Result { - let (v, stripped) = v.strip_prefix("0x").map_or((v, false), |v| (v, true)); - - let len = v.len(); - let is_len_valid = match self.len { - ExpectedLen::Exact(ref slice) => len == 2 * slice.len(), - ExpectedLen::Between(min, ref slice) => len <= 2 * slice.len() && len > 2 * min, - }; - - if !is_len_valid { - return Err(E::invalid_length(v.len(), &self)); - } - - let bytes = match self.len { - ExpectedLen::Exact(slice) => slice, - ExpectedLen::Between(_, slice) => slice, - }; - - from_hex_raw(v, bytes, stripped).map_err(E::custom) - } - - fn visit_string(self, v: String) -> Result { - self.visit_str(&v) - } - } - - deserializer.deserialize_str(Visitor { len }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn arbitrary() { - proptest::proptest!(|(_v1: B160, _v2: B256)| {}); - } - - #[test] - fn should_convert_from_primitive_types_h160() { - let h160 = primitive_types::H160::random(); - let b160: B160 = h160.into(); - let new_h160: primitive_types::H160 = b160.into(); - assert_eq!(h160, new_h160) - } - - #[test] - fn should_convert_to_primitive_types_h160() { - let b160 = B160::random(); - let h160: primitive_types::H160 = b160.into(); - let new_b160: B160 = h160.into(); - assert_eq!(b160, new_b160) - } - - #[test] - fn should_convert_from_primitive_types_h256() { - let h256 = primitive_types::H256::random(); - let b256: B256 = h256.into(); - let new_h256: primitive_types::H256 = b256.into(); - assert_eq!(h256, new_h256) - } - - #[test] - fn should_convert_to_primitive_types_h256() { - let b256 = B256::random(); - let h256: primitive_types::H256 = b256.into(); - let new_b256: B256 = h256.into(); - assert_eq!(b256, new_b256) - } - - #[test] - fn should_convert_to_primitive_types_h256_u256() { - let b256 = B256::random(); - let u256: primitive_types::U256 = b256.into(); - let new_b256: B256 = u256.into(); - assert_eq!(b256, new_b256) - } - - #[test] - fn should_convert_to_ruint_u256() { - let b256 = B256::random(); - let u256: ruint::aliases::U256 = b256.into(); - let new_b256: B256 = u256.into(); - assert_eq!(b256, new_b256) - } -} diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index 5701654f58..d09fffe3ca 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -1,8 +1,7 @@ -use crate::{keccak256, B256, KECCAK_EMPTY}; +use crate::{hex, keccak256, Bytes, B256, KECCAK_EMPTY}; use alloc::{sync::Arc, vec::Vec}; use bitvec::prelude::{bitvec, Lsb0}; use bitvec::vec::BitVec; -use bytes::Bytes; use core::fmt::Debug; /// A map of valid `jump` destinations. @@ -53,7 +52,6 @@ pub enum BytecodeState { #[derive(Clone, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Bytecode { - #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] pub bytecode: Bytes, pub state: BytecodeState, } @@ -61,7 +59,7 @@ pub struct Bytecode { impl Debug for Bytecode { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Bytecode") - .field("bytecode", &hex::encode(&self.bytecode[..])) + .field("bytecode", &self.bytecode) .field("state", &self.state) .finish() } diff --git a/crates/primitives/src/constants.rs b/crates/primitives/src/constants.rs index 4e5664747c..bbbf7c776d 100644 --- a/crates/primitives/src/constants.rs +++ b/crates/primitives/src/constants.rs @@ -1,4 +1,4 @@ -use crate::B160; +use crate::Address; /// Interpreter stack limit pub const STACK_LIMIT: u64 = 1024; @@ -18,8 +18,8 @@ pub const BLOCK_HASH_HISTORY: usize = 256; pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE; /// Precompile 3 is special in few places -pub const PRECOMPILE3: B160 = B160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); - +pub const PRECOMPILE3: Address = + Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); // EIP-4844 constants /// Gas consumption of a single data blob (== blob byte size). pub const GAS_PER_BLOB: u64 = 1 << 17; diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index f376bd6f1e..d6851b6ecb 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -1,7 +1,7 @@ use crate::AccountInfo; use crate::U256; use crate::{Account, Bytecode}; -use crate::{B160, B256}; +use crate::{Address, B256}; use auto_impl::auto_impl; use hashbrown::HashMap as Map; @@ -16,13 +16,13 @@ pub trait Database { type Error; /// Get basic account information. - fn basic(&mut self, address: B160) -> Result, Self::Error>; + fn basic(&mut self, address: Address) -> Result, Self::Error>; /// Get account code by its hash. fn code_by_hash(&mut self, code_hash: B256) -> Result; /// Get storage value of address at index. - fn storage(&mut self, address: B160, index: U256) -> Result; + fn storage(&mut self, address: Address, index: U256) -> Result; /// Get block hash by block number. fn block_hash(&mut self, number: U256) -> Result; @@ -36,7 +36,7 @@ impl From for WrapDatabaseRef { #[auto_impl(&mut, Box)] pub trait DatabaseCommit { - fn commit(&mut self, changes: Map); + fn commit(&mut self, changes: Map); } /// Same as [Database], but uses immutable references. @@ -45,13 +45,13 @@ pub trait DatabaseRef { type Error; /// Get basic account information. - fn basic(&self, address: B160) -> Result, Self::Error>; + fn basic(&self, address: Address) -> Result, Self::Error>; /// Get account code by its hash. fn code_by_hash(&self, code_hash: B256) -> Result; /// Get storage value of address at index. - fn storage(&self, address: B160, index: U256) -> Result; + fn storage(&self, address: Address, index: U256) -> Result; /// Get block hash by block number. fn block_hash(&self, number: U256) -> Result; @@ -64,7 +64,7 @@ impl Database for WrapDatabaseRef { type Error = T::Error; #[inline] - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { self.0.basic(address) } @@ -74,7 +74,7 @@ impl Database for WrapDatabaseRef { } #[inline] - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { self.0.storage(address, index) } @@ -104,7 +104,7 @@ impl<'a, E> Database for RefDBWrapper<'a, E> { type Error = E; #[inline] - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { self.db.basic(address) } @@ -114,7 +114,7 @@ impl<'a, E> Database for RefDBWrapper<'a, E> { } #[inline] - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { self.db.storage(address, index) } diff --git a/crates/primitives/src/db/components.rs b/crates/primitives/src/db/components.rs index 7495c1fc50..d8e5d9d063 100644 --- a/crates/primitives/src/db/components.rs +++ b/crates/primitives/src/db/components.rs @@ -7,7 +7,7 @@ pub use state::{State, StateRef}; use crate::{ db::{Database, DatabaseRef}, - AccountInfo, Bytecode, B160, B256, U256, + AccountInfo, Address, Bytecode, B256, U256, }; #[derive(Debug)] @@ -25,7 +25,7 @@ pub enum DatabaseComponentError { impl Database for DatabaseComponents { type Error = DatabaseComponentError; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { self.state.basic(address).map_err(Self::Error::State) } @@ -35,7 +35,7 @@ impl Database for DatabaseComponents { .map_err(Self::Error::State) } - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { self.state .storage(address, index) .map_err(Self::Error::State) @@ -51,7 +51,7 @@ impl Database for DatabaseComponents { impl DatabaseRef for DatabaseComponents { type Error = DatabaseComponentError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { self.state.basic(address).map_err(Self::Error::State) } @@ -61,7 +61,7 @@ impl DatabaseRef for DatabaseComponents { .map_err(Self::Error::State) } - fn storage(&self, address: B160, index: U256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { self.state .storage(address, index) .map_err(Self::Error::State) diff --git a/crates/primitives/src/db/components/state.rs b/crates/primitives/src/db/components/state.rs index ce38ffb6c0..c59b4408d0 100644 --- a/crates/primitives/src/db/components/state.rs +++ b/crates/primitives/src/db/components/state.rs @@ -1,7 +1,7 @@ //! State database component from [`crate::db::Database`] //! it is used inside [crate::db::DatabaseComponents`] -use crate::{AccountInfo, Bytecode, B160, B256, U256}; +use crate::{AccountInfo, Address, Bytecode, B256, U256}; use alloc::sync::Arc; use auto_impl::auto_impl; use core::ops::Deref; @@ -11,11 +11,11 @@ pub trait State { type Error; /// Get basic account information. - fn basic(&mut self, address: B160) -> Result, Self::Error>; + fn basic(&mut self, address: Address) -> Result, Self::Error>; /// Get account code by its hash fn code_by_hash(&mut self, code_hash: B256) -> Result; /// Get storage value of address at index. - fn storage(&mut self, address: B160, index: U256) -> Result; + fn storage(&mut self, address: Address, index: U256) -> Result; } #[auto_impl(&, Box, Arc)] @@ -23,13 +23,13 @@ pub trait StateRef { type Error; /// Whether account at address exists. - //fn exists(&self, address: B160) -> Option; + //fn exists(&self, address: Address) -> Option; /// Get basic account information. - fn basic(&self, address: B160) -> Result, Self::Error>; + fn basic(&self, address: Address) -> Result, Self::Error>; /// Get account code by its hash fn code_by_hash(&self, code_hash: B256) -> Result; /// Get storage value of address at index. - fn storage(&self, address: B160, index: U256) -> Result; + fn storage(&self, address: Address, index: U256) -> Result; } impl State for &T @@ -38,7 +38,7 @@ where { type Error = ::Error; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { StateRef::basic(*self, address) } @@ -46,7 +46,7 @@ where StateRef::code_by_hash(*self, code_hash) } - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { StateRef::storage(*self, address, index) } } @@ -57,7 +57,7 @@ where { type Error = ::Error; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { self.deref().basic(address) } @@ -65,7 +65,7 @@ where self.deref().code_by_hash(code_hash) } - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { self.deref().storage(address, index) } } diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index aac60a45ec..1c64b735fb 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,9 +1,8 @@ use crate::{ - alloc::vec::Vec, calc_blob_gasprice, Account, InvalidHeader, InvalidTransaction, Spec, SpecId, - B160, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, - VERSIONED_HASH_VERSION_KZG, + alloc::vec::Vec, calc_blob_gasprice, Account, Address, Bytes, InvalidHeader, + InvalidTransaction, Spec, SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, + MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, }; -use bytes::Bytes; use core::cmp::{min, Ordering}; #[derive(Clone, Debug, Default, PartialEq, Eq)] @@ -23,7 +22,8 @@ pub struct BlockEnv { /// Coinbase or miner or address that created and signed the block. /// /// This is the receiver address of all the gas spent in the block. - pub coinbase: B160, + pub coinbase: Address, + /// The timestamp of the block in seconds since the UNIX epoch. pub timestamp: U256, /// The gas limit of the block. @@ -129,8 +129,8 @@ impl BlockEnv { #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TxEnv { - /// The caller, author or signer of the transaction. - pub caller: B160, + /// Caller aka Author aka transaction signer. + pub caller: Address, /// The gas limit of the transaction. pub gas_limit: u64, /// The gas price of the transaction. @@ -140,7 +140,6 @@ pub struct TxEnv { /// The value sent to `transact_to`. pub value: U256, /// The data of the transaction. - #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] pub data: Bytes, /// The nonce of the transaction. If set to `None`, no checks are performed. pub nonce: Option, @@ -157,7 +156,7 @@ pub struct TxEnv { /// Added in [EIP-2930]. /// /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 - pub access_list: Vec<(B160, Vec)>, + pub access_list: Vec<(Address, Vec)>, /// The priority fee per gas. /// @@ -173,6 +172,7 @@ pub struct TxEnv { /// /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 pub blob_hashes: Vec, + /// The max fee per blob gas. /// /// Incorporated as part of the Cancun upgrade via [EIP-4844]. @@ -200,7 +200,7 @@ impl TxEnv { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TransactTo { /// Simple call to an address. - Call(B160), + Call(Address), /// Contract creation. Create(CreateScheme), } @@ -208,7 +208,7 @@ pub enum TransactTo { impl TransactTo { /// Calls the given address. #[inline] - pub fn call(address: B160) -> Self { + pub fn call(address: Address) -> Self { Self::Call(address) } @@ -414,12 +414,12 @@ impl Default for BlockEnv { fn default() -> Self { Self { number: U256::ZERO, - coinbase: B160::zero(), + coinbase: Address::ZERO, timestamp: U256::from(1), gas_limit: U256::MAX, basefee: U256::ZERO, difficulty: U256::ZERO, - prevrandao: Some(B256::zero()), + prevrandao: Some(B256::ZERO), blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new(0)), } } @@ -428,11 +428,11 @@ impl Default for BlockEnv { impl Default for TxEnv { fn default() -> Self { Self { - caller: B160::zero(), + caller: Address::ZERO, gas_limit: u64::MAX, gas_price: U256::ZERO, gas_priority_fee: None, - transact_to: TransactTo::Call(B160::zero()), // will do nothing + transact_to: TransactTo::Call(Address::ZERO), // will do nothing value: U256::ZERO, data: Bytes::new(), chain_id: None, @@ -693,7 +693,7 @@ mod tests { // Set the optimism flag and source hash. let mut env = Env::default(); env.cfg.optimism = true; - env.tx.optimism.source_hash = Some(B256::zero()); + env.tx.optimism.source_hash = Some(B256::ZERO); assert!(env.validate_tx::().is_ok()); } @@ -703,7 +703,7 @@ mod tests { // Set the optimism flag and source hash. let mut env = Env::default(); env.cfg.optimism = true; - env.tx.optimism.source_hash = Some(B256::zero()); + env.tx.optimism.source_hash = Some(B256::ZERO); // Nonce and balance checks should be skipped for deposit transactions. assert!(env @@ -725,7 +725,7 @@ mod tests { #[test] fn test_validate_tx_access_list() { let mut env = Env::default(); - env.tx.access_list = vec![(B160::zero(), vec![])]; + env.tx.access_list = vec![(Address::ZERO, vec![])]; assert_eq!( env.validate_tx::(), Err(InvalidTransaction::AccessListNotSupported) diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 6e1803a770..00cda698d4 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -1,8 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +#![warn(unused_crate_dependencies)] extern crate alloc; -pub mod bits; pub mod bytecode; pub mod constants; pub mod db; @@ -16,30 +16,20 @@ pub mod specification; pub mod state; pub mod utilities; -pub use bits::B160; -pub use bits::B256; +pub use alloy_primitives::{ + self, address, b256, bytes, fixed_bytes, hex, hex_literal, ruint, uint, Address, Bytes, + FixedBytes, B256, U256, +}; pub use bitvec; pub use bytecode::*; -pub use bytes; -pub use bytes::Bytes; pub use constants::*; pub use env::*; pub use hashbrown::{hash_map, hash_set, HashMap, HashSet}; -pub use hex; -pub use hex_literal; #[cfg(feature = "c-kzg")] pub use kzg::{EnvKzgSettings, KzgSettings}; pub use log::Log; pub use precompile::*; pub use result::*; -pub use ruint; -pub use ruint::aliases::U256; -pub use ruint::uint; pub use specification::*; pub use state::*; pub use utilities::*; - -/// Address type is last 20 bytes of hash of ethereum account -pub type Address = B160; -/// Hash, in Ethereum usually keccak256. -pub type Hash = B256; diff --git a/crates/primitives/src/log.rs b/crates/primitives/src/log.rs index 3c16ed035a..578f0b243f 100644 --- a/crates/primitives/src/log.rs +++ b/crates/primitives/src/log.rs @@ -1,11 +1,11 @@ -use crate::{bytes::Bytes, B160, B256}; +use crate::{Address, Bytes, B256}; use alloc::vec::Vec; +use alloy_rlp::{RlpDecodable, RlpEncodable}; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpDecodable, RlpEncodable)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Log { - pub address: B160, + pub address: Address, pub topics: Vec, - #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] pub data: Bytes, } diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 934a66d78a..e5f230099c 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,8 +1,6 @@ -use crate::{Log, State, B160}; +use crate::{Address, Bytes, Log, State, U256}; use alloc::vec::Vec; -use bytes::Bytes; use core::fmt; -use ruint::aliases::U256; /// Result of EVM execution. pub type EVMResult = EVMResultGeneric; @@ -98,12 +96,8 @@ impl ExecutionResult { #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Output { - #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] Call(Bytes), - Create( - #[cfg_attr(feature = "serde", serde(with = "crate::utilities::serde_hex_bytes"))] Bytes, - Option, - ), + Create(Bytes, Option
), } impl Output { diff --git a/crates/primitives/src/state.rs b/crates/primitives/src/state.rs index 3e9b0aa604..b626a76cfd 100644 --- a/crates/primitives/src/state.rs +++ b/crates/primitives/src/state.rs @@ -1,4 +1,4 @@ -use crate::{Bytecode, B160, B256, KECCAK_EMPTY, U256}; +use crate::{Address, Bytecode, B256, KECCAK_EMPTY, U256}; use bitflags::bitflags; use hashbrown::HashMap; @@ -41,10 +41,11 @@ impl Default for AccountStatus { } } -pub type State = HashMap; +pub type State = HashMap; /// Structure used for EIP-1153 transient storage. -pub type TransientStorage = HashMap<(B160, U256), U256>; +pub type TransientStorage = HashMap<(Address, U256), U256>; + pub type Storage = HashMap; impl Account { @@ -213,7 +214,7 @@ impl AccountInfo { } pub fn is_empty(&self) -> bool { - let code_empty = self.code_hash == KECCAK_EMPTY || self.code_hash == B256::zero(); + let code_empty = self.code_hash == KECCAK_EMPTY || self.code_hash == B256::ZERO; self.balance == U256::ZERO && self.nonce == 0 && code_empty } diff --git a/crates/primitives/src/utilities.rs b/crates/primitives/src/utilities.rs index 83b6fe69b9..4d2ee7ff0d 100644 --- a/crates/primitives/src/utilities.rs +++ b/crates/primitives/src/utilities.rs @@ -1,36 +1,23 @@ use crate::{ - B160, B256, BLOB_GASPRICE_UPDATE_FRACTION, MIN_BLOB_GASPRICE, TARGET_BLOB_GAS_PER_BLOCK, U256, + b256, Address, B256, BLOB_GASPRICE_UPDATE_FRACTION, MIN_BLOB_GASPRICE, + TARGET_BLOB_GAS_PER_BLOCK, U256, }; -use hex_literal::hex; -use sha3::{Digest, Keccak256}; +pub use alloy_primitives::keccak256; -pub const KECCAK_EMPTY: B256 = B256(hex!( - "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" -)); +/// The Keccak-256 hash of the empty string `""`. +pub const KECCAK_EMPTY: B256 = + b256!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); -#[inline(always)] -pub fn keccak256(input: &[u8]) -> B256 { - B256(Keccak256::digest(input)[..].try_into().unwrap()) -} - -/// Returns the address for the legacy `CREATE` scheme: [`crate::env::CreateScheme::Create`] -pub fn create_address(caller: B160, nonce: u64) -> B160 { - let mut stream = rlp::RlpStream::new_list(2); - stream.append(&caller.0.as_ref()); - stream.append(&nonce); - let out = keccak256(&stream.out()); - B160(out[12..].try_into().unwrap()) +/// Returns the address for the legacy `CREATE` scheme: [`CreateScheme::Create`] +#[inline] +pub fn create_address(caller: Address, nonce: u64) -> Address { + caller.create(nonce) } -/// Returns the address for the `CREATE2` scheme: [`crate::env::CreateScheme::Create2`] -pub fn create2_address(caller: B160, code_hash: B256, salt: U256) -> B160 { - let mut hasher = Keccak256::new(); - hasher.update([0xff]); - hasher.update(&caller[..]); - hasher.update(salt.to_be_bytes::<{ U256::BYTES }>()); - hasher.update(&code_hash[..]); - - B160(hasher.finalize().as_slice()[12..].try_into().unwrap()) +/// Returns the address for the `CREATE2` scheme: [`CreateScheme::Create2`] +#[inline] +pub fn create2_address(caller: Address, code_hash: B256, salt: U256) -> Address { + caller.create2(salt.to_be_bytes::<32>(), code_hash) } /// Calculates the `excess_blob_gas` from the parent header's `blob_gas_used` and `excess_blob_gas`. @@ -82,35 +69,6 @@ pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u128 { output / denominator } -/// Serde functions to serde as [bytes::Bytes] hex string -#[cfg(feature = "serde")] -pub mod serde_hex_bytes { - use alloc::string::{String, ToString}; - use serde::{Deserialize, Deserializer, Serializer}; - - pub fn serialize(x: T, s: S) -> Result - where - S: Serializer, - T: AsRef<[u8]>, - { - s.serialize_str(&alloc::format!("0x{}", hex::encode(x.as_ref()))) - } - - pub fn deserialize<'de, D>(d: D) -> Result - where - D: Deserializer<'de>, - { - let value = String::deserialize(d)?; - if let Some(value) = value.strip_prefix("0x") { - hex::decode(value) - } else { - hex::decode(&value) - } - .map(Into::into) - .map_err(|e| serde::de::Error::custom(e.to_string())) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index ea0553fcb7..e886fb6cca 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Dragan Rakita "] -description = "REVM - Rust Ethereum Virtual Machine" +description = "revm - Rust Ethereum Virtual Machine" edition = "2021" keywords = ["no_std", "ethereum", "evm", "revm"] license = "MIT" @@ -30,11 +30,8 @@ ethers-core = { version = "2.0", optional = true } futures = { version = "0.3.27", optional = true } [dev-dependencies] -hex-literal = "0.4" ethers-contract = { version = "2.0.10", default-features = false } -hex = "0.4.3" anyhow = "1.0.75" -bytes = "1.5.0" criterion = "0.5" [features] @@ -43,6 +40,8 @@ std = ["revm-interpreter/std", "revm-precompile/std"] serde = ["dep:serde", "dep:serde_json", "revm-interpreter/serde"] arbitrary = ["revm-interpreter/arbitrary"] +optimism = ["revm-interpreter/optimism", "revm-precompile/optimism"] + ethersdb = ["std", "tokio", "futures", "ethers-providers", "ethers-core"] dev = [ @@ -68,7 +67,6 @@ c-kzg = ["revm-precompile/c-kzg"] # deprecated features web3db = [] with-serde = [] -optimism = ["revm-interpreter/optimism", "revm-precompile/optimism"] [[example]] name = "fork_ref_transact" diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index d51e174d0c..37056277f9 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -1,11 +1,12 @@ -use bytes::Bytes; use criterion::{ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, }; use revm::{ db::BenchmarkDB, interpreter::{analysis::to_analysed, BytecodeLocked, Contract, DummyHost, Interpreter}, - primitives::{BerlinSpec, Bytecode, BytecodeState, TransactTo, U256}, + primitives::{ + address, bytes, hex, BerlinSpec, Bytecode, BytecodeState, Bytes, TransactTo, U256, + }, }; use std::time::Duration; @@ -14,16 +15,10 @@ type Evm = revm::EVM; fn analysis(c: &mut Criterion) { let mut evm = revm::new(); - evm.env.tx.caller = "0x1000000000000000000000000000000000000000" - .parse() - .unwrap(); - evm.env.tx.transact_to = TransactTo::Call( - "0x0000000000000000000000000000000000000000" - .parse() - .unwrap(), - ); - // evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); - evm.env.tx.data = Bytes::from(hex::decode("8035F0CE").unwrap()); + evm.env.tx.caller = address!("1000000000000000000000000000000000000000"); + evm.env.tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + // evm.env.tx.data = bytes!("30627b7c"); + evm.env.tx.data = bytes!("8035F0CE"); let contract_data: Bytes = hex::decode(ANALYSIS).unwrap().into(); @@ -52,15 +47,9 @@ fn snailtracer(c: &mut Criterion) { let mut evm = revm::new(); evm.database(BenchmarkDB::new_bytecode(bytecode(SNAILTRACER))); - evm.env.tx.caller = "0x1000000000000000000000000000000000000000" - .parse() - .unwrap(); - evm.env.tx.transact_to = TransactTo::Call( - "0x0000000000000000000000000000000000000000" - .parse() - .unwrap(), - ); - evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); + evm.env.tx.caller = address!("1000000000000000000000000000000000000000"); + evm.env.tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + evm.env.tx.data = bytes!("30627b7c"); let mut g = c.benchmark_group("snailtracer"); g.noise_threshold(0.03) @@ -76,14 +65,8 @@ fn transfer(c: &mut Criterion) { let mut evm = revm::new(); evm.database(BenchmarkDB::new_bytecode(Bytecode::new())); - evm.env.tx.caller = "0x0000000000000000000000000000000000000001" - .parse() - .unwrap(); - evm.env.tx.transact_to = TransactTo::Call( - "0x0000000000000000000000000000000000000000" - .parse() - .unwrap(), - ); + evm.env.tx.caller = address!("0000000000000000000000000000000000000001"); + evm.env.tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); evm.env.tx.value = U256::from(10); let mut g = c.benchmark_group("transfer"); diff --git a/crates/revm/src/db/emptydb.rs b/crates/revm/src/db/emptydb.rs index eeaaaf928d..0dbf31df0f 100644 --- a/crates/revm/src/db/emptydb.rs +++ b/crates/revm/src/db/emptydb.rs @@ -1,7 +1,7 @@ use core::{convert::Infallible, fmt, marker::PhantomData}; use revm_interpreter::primitives::{ db::{Database, DatabaseRef}, - AccountInfo, Bytecode, B160, B256, U256, + AccountInfo, Address, Bytecode, B256, U256, }; /// An empty database that always returns default values when queried. @@ -61,7 +61,7 @@ impl Database for EmptyDBTyped { type Error = E; #[inline] - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { ::basic(self, address) } @@ -71,7 +71,7 @@ impl Database for EmptyDBTyped { } #[inline] - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { ::storage(self, address, index) } @@ -85,7 +85,7 @@ impl DatabaseRef for EmptyDBTyped { type Error = E; #[inline] - fn basic(&self, _address: B160) -> Result, Self::Error> { + fn basic(&self, _address: Address) -> Result, Self::Error> { Ok(None) } @@ -95,7 +95,7 @@ impl DatabaseRef for EmptyDBTyped { } #[inline] - fn storage(&self, _address: B160, _index: U256) -> Result { + fn storage(&self, _address: Address, _index: U256) -> Result { Ok(U256::default()) } diff --git a/crates/revm/src/db/ethersdb.rs b/crates/revm/src/db/ethersdb.rs index 69bbc6b5b8..498c810503 100644 --- a/crates/revm/src/db/ethersdb.rs +++ b/crates/revm/src/db/ethersdb.rs @@ -1,4 +1,4 @@ -use crate::primitives::{AccountInfo, Bytecode, B160, B256, KECCAK_EMPTY, U256}; +use crate::primitives::{AccountInfo, Address, Bytecode, B256, KECCAK_EMPTY, U256}; use crate::Database; use ethers_core::types::{BlockId, H160 as eH160, H256, U64 as eU64}; use ethers_providers::Middleware; @@ -49,8 +49,8 @@ impl EthersDB { impl Database for EthersDB { type Error = (); - fn basic(&mut self, address: B160) -> Result, Self::Error> { - let add = eH160::from(address.0); + fn basic(&mut self, address: Address) -> Result, Self::Error> { + let add = eH160::from(address.0 .0); let f = async { let nonce = self.client.get_transaction_count(add, self.block_number); @@ -60,10 +60,8 @@ impl Database for EthersDB { }; let (nonce, balance, code) = self.block_on(f); // panic on not getting data? - let bytecode = Bytecode::new_raw( - code.unwrap_or_else(|e| panic!("ethers get code error: {e:?}")) - .0, - ); + let bytecode = code.unwrap_or_else(|e| panic!("ethers get code error: {e:?}")); + let bytecode = Bytecode::new_raw(bytecode.0.into()); let code_hash = bytecode.hash_slow(); Ok(Some(AccountInfo::new( U256::from_limbs( @@ -84,8 +82,8 @@ impl Database for EthersDB { // not needed because we already load code with basic info } - fn storage(&mut self, address: B160, index: U256) -> Result { - let add = eH160::from(address.0); + fn storage(&mut self, address: Address, index: U256) -> Result { + let add = eH160::from(address.0 .0); let index = H256::from(index.to_be_bytes()); let f = async { let storage = self @@ -111,7 +109,7 @@ impl Database for EthersDB { .ok() .flatten() }; - Ok(B256(self.block_on(f).unwrap().hash.unwrap().0)) + Ok(B256::new(self.block_on(f).unwrap().hash.unwrap().0)) } } diff --git a/crates/revm/src/db/in_memory_db.rs b/crates/revm/src/db/in_memory_db.rs index 4909b0bab2..d395d2aa44 100644 --- a/crates/revm/src/db/in_memory_db.rs +++ b/crates/revm/src/db/in_memory_db.rs @@ -1,6 +1,7 @@ use super::{DatabaseCommit, DatabaseRef, EmptyDB}; use crate::primitives::{ - hash_map::Entry, Account, AccountInfo, Bytecode, HashMap, Log, B160, B256, KECCAK_EMPTY, U256, + hash_map::Entry, Account, AccountInfo, Address, Bytecode, HashMap, Log, B256, KECCAK_EMPTY, + U256, }; use crate::Database; use alloc::vec::Vec; @@ -20,7 +21,7 @@ pub type InMemoryDB = CacheDB; pub struct CacheDB { /// Account info where None means it is not existing. Not existing state is needed for Pre TANGERINE forks. /// `code` is always `None`, and bytecode can be found in `contracts`. - pub accounts: HashMap, + pub accounts: HashMap, /// Tracks all contracts by their code hash. pub contracts: HashMap, /// All logs that were committed via [DatabaseCommit::commit]. @@ -43,7 +44,7 @@ impl CacheDB { pub fn new(db: ExtDB) -> Self { let mut contracts = HashMap::new(); contracts.insert(KECCAK_EMPTY, Bytecode::new()); - contracts.insert(B256::zero(), Bytecode::new()); + contracts.insert(B256::ZERO, Bytecode::new()); Self { accounts: HashMap::new(), contracts, @@ -69,13 +70,13 @@ impl CacheDB { .or_insert_with(|| code.clone()); } } - if account.code_hash == B256::zero() { + if account.code_hash == B256::ZERO { account.code_hash = KECCAK_EMPTY; } } /// Insert account info but not override storage - pub fn insert_account_info(&mut self, address: B160, mut info: AccountInfo) { + pub fn insert_account_info(&mut self, address: Address, mut info: AccountInfo) { self.insert_contract(&mut info); self.accounts.entry(address).or_default().info = info; } @@ -83,7 +84,7 @@ impl CacheDB { /// Returns the account for the given address. /// /// If the account was not found in the cache, it will be loaded from the underlying database. - pub fn load_account(&mut self, address: B160) -> Result<&mut DbAccount, ExtDB::Error> { + pub fn load_account(&mut self, address: Address) -> Result<&mut DbAccount, ExtDB::Error> { let db = &self.db; match self.accounts.entry(address) { Entry::Occupied(entry) => Ok(entry.into_mut()), @@ -101,7 +102,7 @@ impl CacheDB { /// insert account storage without overriding account info pub fn insert_account_storage( &mut self, - address: B160, + address: Address, slot: U256, value: U256, ) -> Result<(), ExtDB::Error> { @@ -113,7 +114,7 @@ impl CacheDB { /// replace account storage without overriding account info pub fn replace_account_storage( &mut self, - address: B160, + address: Address, storage: HashMap, ) -> Result<(), ExtDB::Error> { let account = self.load_account(address)?; @@ -124,7 +125,7 @@ impl CacheDB { } impl DatabaseCommit for CacheDB { - fn commit(&mut self, changes: HashMap) { + fn commit(&mut self, changes: HashMap) { for (address, mut account) in changes { if !account.is_touched() { continue; @@ -164,7 +165,7 @@ impl DatabaseCommit for CacheDB { impl Database for CacheDB { type Error = ExtDB::Error; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { let basic = match self.accounts.entry(address) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => entry.insert( @@ -193,7 +194,7 @@ impl Database for CacheDB { /// Get the value in an account's storage slot. /// /// It is assumed that account is already loaded. - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { match self.accounts.entry(address) { Entry::Occupied(mut acc_entry) => { let acc_entry = acc_entry.get_mut(); @@ -245,7 +246,7 @@ impl Database for CacheDB { impl DatabaseRef for CacheDB { type Error = ExtDB::Error; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { match self.accounts.get(&address) { Some(acc) => Ok(acc.info()), None => self.db.basic(address), @@ -259,7 +260,7 @@ impl DatabaseRef for CacheDB { } } - fn storage(&self, address: B160, index: U256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { match self.accounts.get(&address) { Some(acc_entry) => match acc_entry.storage.get(&index) { Some(entry) => Ok(*entry), @@ -366,8 +367,8 @@ impl BenchmarkDB { impl Database for BenchmarkDB { type Error = Infallible; /// Get basic account information. - fn basic(&mut self, address: B160) -> Result, Self::Error> { - if address == B160::zero() { + fn basic(&mut self, address: Address) -> Result, Self::Error> { + if address == Address::ZERO { return Ok(Some(AccountInfo { nonce: 1, balance: U256::from(10000000), @@ -375,7 +376,7 @@ impl Database for BenchmarkDB { code_hash: self.1, })); } - if address == B160::from(1) { + if address == Address::with_last_byte(1) { return Ok(Some(AccountInfo { nonce: 0, balance: U256::from(10000000), @@ -392,7 +393,7 @@ impl Database for BenchmarkDB { } /// Get storage value of address at index. - fn storage(&mut self, _address: B160, _index: U256) -> Result { + fn storage(&mut self, _address: Address, _index: U256) -> Result { Ok(U256::default()) } @@ -405,11 +406,11 @@ impl Database for BenchmarkDB { #[cfg(test)] mod tests { use super::{CacheDB, EmptyDB}; - use crate::primitives::{db::Database, AccountInfo, U256}; + use crate::primitives::{db::Database, AccountInfo, Address, U256}; #[test] fn test_insert_account_storage() { - let account = 42.into(); + let account = Address::with_last_byte(42); let nonce = 42; let mut init_state = CacheDB::new(EmptyDB::default()); init_state.insert_account_info( @@ -430,7 +431,7 @@ mod tests { #[test] fn test_replace_account_storage() { - let account = 42.into(); + let account = Address::with_last_byte(42); let nonce = 42; let mut init_state = CacheDB::new(EmptyDB::default()); init_state.insert_account_info( diff --git a/crates/revm/src/db/states/bundle_state.rs b/crates/revm/src/db/states/bundle_state.rs index baa5e570a0..4c2afd55d9 100644 --- a/crates/revm/src/db/states/bundle_state.rs +++ b/crates/revm/src/db/states/bundle_state.rs @@ -10,21 +10,21 @@ use alloc::{ use core::ops::RangeInclusive; use revm_interpreter::primitives::{ hash_map::{self, Entry}, - AccountInfo, Bytecode, HashMap, HashSet, StorageSlot, B160, B256, KECCAK_EMPTY, U256, + AccountInfo, Address, Bytecode, HashMap, HashSet, StorageSlot, B256, KECCAK_EMPTY, U256, }; /// This builder is used to help to facilitate the initialization of `BundleState` struct #[derive(Debug)] pub struct BundleBuilder { - states: HashSet, - state_original: HashMap, - state_present: HashMap, - state_storage: HashMap>, + states: HashSet
, + state_original: HashMap, + state_present: HashMap, + state_storage: HashMap>, - reverts: BTreeSet<(u64, B160)>, + reverts: BTreeSet<(u64, Address)>, revert_range: RangeInclusive, - revert_account: HashMap<(u64, B160), Option>>, - revert_storage: HashMap<(u64, B160), Vec<(U256, U256)>>, + revert_account: HashMap<(u64, Address), Option>>, + revert_storage: HashMap<(u64, Address), Vec<(U256, U256)>>, contracts: HashMap, } @@ -40,7 +40,6 @@ pub enum OriginalValuesKnown { /// original values so this option should be used. No, } - impl OriginalValuesKnown { /// Original value is not known for sure. pub fn is_not_known(&self) -> bool { @@ -76,27 +75,27 @@ impl BundleBuilder { } /// Collect address info of BundleState state - pub fn state_address(mut self, address: B160) -> Self { + pub fn state_address(mut self, address: Address) -> Self { self.states.insert(address); self } /// Collect account info of BundleState state - pub fn state_original_account_info(mut self, address: B160, original: AccountInfo) -> Self { + pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self { self.states.insert(address); self.state_original.insert(address, original); self } /// Collect account info of BundleState state - pub fn state_present_account_info(mut self, address: B160, present: AccountInfo) -> Self { + pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self { self.states.insert(address); self.state_present.insert(address, present); self } /// Collect storage info of BundleState state - pub fn state_storage(mut self, address: B160, storage: HashMap) -> Self { + pub fn state_storage(mut self, address: Address, storage: HashMap) -> Self { self.states.insert(address); self.state_storage.insert(address, storage); self @@ -106,7 +105,7 @@ impl BundleBuilder { /// /// `block_number` must respect `revert_range`, or the input /// will be ignored during the final build process - pub fn revert_address(mut self, block_number: u64, address: B160) -> Self { + pub fn revert_address(mut self, block_number: u64, address: Address) -> Self { self.reverts.insert((block_number, address)); self } @@ -118,7 +117,7 @@ impl BundleBuilder { pub fn revert_account_info( mut self, block_number: u64, - address: B160, + address: Address, account: Option>, ) -> Self { self.reverts.insert((block_number, address)); @@ -133,7 +132,7 @@ impl BundleBuilder { pub fn revert_storage( mut self, block_number: u64, - address: B160, + address: Address, storage: Vec<(U256, U256)>, ) -> Self { self.reverts.insert((block_number, address)); @@ -252,7 +251,7 @@ impl BundleRetention { #[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct BundleState { /// Account state. - pub state: HashMap, + pub state: HashMap, /// All created contracts in this block. pub contracts: HashMap, /// Changes to revert. @@ -279,7 +278,7 @@ impl BundleState { pub fn new( state: impl IntoIterator< Item = ( - B160, + Address, Option, Option, HashMap, @@ -288,7 +287,7 @@ impl BundleState { reverts: impl IntoIterator< Item = impl IntoIterator< Item = ( - B160, + Address, Option>, impl IntoIterator, ), @@ -361,7 +360,7 @@ impl BundleState { } /// Return reference to the state. - pub fn state(&self) -> &HashMap { + pub fn state(&self) -> &HashMap { &self.state } @@ -376,7 +375,7 @@ impl BundleState { } /// Get account from state - pub fn account(&self, address: &B160) -> Option<&BundleAccount> { + pub fn account(&self, address: &Address) -> Option<&BundleAccount> { self.state.get(address) } @@ -664,7 +663,7 @@ mod tests { #[test] fn transition_states() { // dummy data - let address = B160([0x01; 20]); + let address = Address::new([0x01; 20]); let acc1 = AccountInfo { balance: U256::from(10), nonce: 1, @@ -692,12 +691,12 @@ mod tests { ); } - const fn account1() -> B160 { - B160([0x60; 20]) + const fn account1() -> Address { + Address::new([0x60; 20]) } - const fn account2() -> B160 { - B160([0x61; 20]) + const fn account2() -> Address { + Address::new([0x61; 20]) } fn slot1() -> U256 { diff --git a/crates/revm/src/db/states/cache.rs b/crates/revm/src/db/states/cache.rs index 9dc8d98642..43e0da66c0 100644 --- a/crates/revm/src/db/states/cache.rs +++ b/crates/revm/src/db/states/cache.rs @@ -2,7 +2,9 @@ use super::{ plain_account::PlainStorage, transition_account::TransitionAccount, CacheAccount, PlainAccount, }; use alloc::vec::Vec; -use revm_interpreter::primitives::{AccountInfo, Bytecode, HashMap, State as EVMState, B160, B256}; +use revm_interpreter::primitives::{ + AccountInfo, Address, Bytecode, HashMap, State as EVMState, B256, +}; /// Cache state contains both modified and original values. /// @@ -13,7 +15,7 @@ use revm_interpreter::primitives::{AccountInfo, Bytecode, HashMap, State as EVMS #[derive(Debug, Clone)] pub struct CacheState { /// Block state account with account state - pub accounts: HashMap, + pub accounts: HashMap, /// created contracts /// TODO add bytecode counter for number of bytecodes added/removed. pub contracts: HashMap, @@ -43,8 +45,9 @@ impl CacheState { } /// Helper function that returns all accounts. + /// /// Used inside tests to generate merkle tree. - pub fn trie_account(&self) -> impl IntoIterator { + pub fn trie_account(&self) -> impl IntoIterator { self.accounts.iter().filter_map(|(address, account)| { account .account @@ -54,13 +57,13 @@ impl CacheState { } /// Insert not existing account. - pub fn insert_not_existing(&mut self, address: B160) { + pub fn insert_not_existing(&mut self, address: Address) { self.accounts .insert(address, CacheAccount::new_loaded_not_existing()); } /// Insert Loaded (Or LoadedEmptyEip161 if account is empty) account. - pub fn insert_account(&mut self, address: B160, info: AccountInfo) { + pub fn insert_account(&mut self, address: Address, info: AccountInfo) { let account = if !info.is_empty() { CacheAccount::new_loaded(info, HashMap::default()) } else { @@ -72,7 +75,7 @@ impl CacheState { /// Similar to `insert_account` but with storage. pub fn insert_account_with_storage( &mut self, - address: B160, + address: Address, info: AccountInfo, storage: PlainStorage, ) { @@ -86,7 +89,7 @@ impl CacheState { /// Apply output of revm execution and create TransactionAccount /// that is used to build BundleState. - pub fn apply_evm_state(&mut self, evm_state: EVMState) -> Vec<(B160, TransitionAccount)> { + pub fn apply_evm_state(&mut self, evm_state: EVMState) -> Vec<(Address, TransitionAccount)> { let mut transitions = Vec::with_capacity(evm_state.len()); for (address, account) in evm_state { if !account.is_touched() { diff --git a/crates/revm/src/db/states/changes.rs b/crates/revm/src/db/states/changes.rs index 34519f65bd..4039da01a6 100644 --- a/crates/revm/src/db/states/changes.rs +++ b/crates/revm/src/db/states/changes.rs @@ -1,6 +1,6 @@ use super::RevertToSlot; use alloc::vec::Vec; -use revm_interpreter::primitives::{AccountInfo, Bytecode, B160, B256, U256}; +use revm_interpreter::primitives::{AccountInfo, Address, Bytecode, B256, U256}; /// accounts/storages/contracts for inclusion into database. /// Structure is made so it is easier to apply directly to database @@ -11,7 +11,7 @@ use revm_interpreter::primitives::{AccountInfo, Bytecode, B160, B256, U256}; #[derive(Clone, Debug, Default)] pub struct StateChangeset { /// Vector of **not** sorted accounts information. - pub accounts: Vec<(B160, Option)>, + pub accounts: Vec<(Address, Option)>, /// Vector of **not** sorted storage. pub storage: Vec, /// Vector of contracts by bytecode hash. **not** sorted. @@ -23,7 +23,7 @@ pub struct StateChangeset { #[derive(Clone, Debug, PartialEq, Eq, Default)] pub struct PlainStorageChangeset { /// Address of account - pub address: B160, + pub address: Address, /// Wipe storage, pub wipe_storage: bool, /// Storage key value pairs. @@ -34,7 +34,7 @@ pub struct PlainStorageChangeset { #[derive(Clone, Debug, PartialEq, Eq, Default)] pub struct PlainStorageRevert { /// Address of account - pub address: B160, + pub address: Address, /// Is storage wiped in this revert. Wiped flag is set on /// first known selfdestruct and would require clearing the /// state of this storage from database (And moving it to revert). @@ -52,7 +52,7 @@ pub struct PlainStateReverts { /// Vector of account with removed contracts bytecode /// /// Note: If AccountInfo is None means that account needs to be removed. - pub accounts: Vec)>>, + pub accounts: Vec)>>, /// Vector of storage with its address. pub storage: Vec>, } @@ -68,4 +68,4 @@ impl PlainStateReverts { } /// Storage reverts -pub type StorageRevert = Vec)>>; +pub type StorageRevert = Vec)>>; diff --git a/crates/revm/src/db/states/reverts.rs b/crates/revm/src/db/states/reverts.rs index c4b1346708..3166e1a1f6 100644 --- a/crates/revm/src/db/states/reverts.rs +++ b/crates/revm/src/db/states/reverts.rs @@ -4,14 +4,14 @@ use super::{ }; use alloc::vec::Vec; use core::ops::{Deref, DerefMut}; -use revm_interpreter::primitives::{AccountInfo, HashMap, B160, U256}; +use revm_interpreter::primitives::{AccountInfo, Address, HashMap, U256}; /// Contains reverts of multiple account in multiple transitions (Transitions as a block). #[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct Reverts(Vec>); +pub struct Reverts(Vec>); impl Deref for Reverts { - type Target = Vec>; + type Target = Vec>; fn deref(&self) -> &Self::Target { &self.0 @@ -26,7 +26,7 @@ impl DerefMut for Reverts { impl Reverts { /// Create new reverts - pub fn new(reverts: Vec>) -> Self { + pub fn new(reverts: Vec>) -> Self { Self(reverts) } diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index 7fba19fa20..5166a0a82b 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -10,7 +10,7 @@ use alloc::{ }; use revm_interpreter::primitives::{ db::{Database, DatabaseCommit}, - hash_map, Account, AccountInfo, Bytecode, HashMap, B160, B256, BLOCK_HASH_HISTORY, U256, + hash_map, Account, AccountInfo, Address, Bytecode, HashMap, B256, BLOCK_HASH_HISTORY, U256, }; /// Database boxed with a lifetime and Send. @@ -84,7 +84,7 @@ impl State { /// Update will create transitions for all accounts that are updated. pub fn increment_balances( &mut self, - balances: impl IntoIterator, + balances: impl IntoIterator, ) -> Result<(), DB::Error> { // make transition and update cache state let mut transitions = Vec::new(); @@ -104,7 +104,7 @@ impl State { /// It is used for DAO hardfork state change to move values from given accounts. pub fn drain_balances( &mut self, - addresses: impl IntoIterator, + addresses: impl IntoIterator, ) -> Result, DB::Error> { // make transition and update cache state let mut transitions = Vec::new(); @@ -127,17 +127,17 @@ impl State { self.cache.set_state_clear_flag(has_state_clear); } - pub fn insert_not_existing(&mut self, address: B160) { + pub fn insert_not_existing(&mut self, address: Address) { self.cache.insert_not_existing(address) } - pub fn insert_account(&mut self, address: B160, info: AccountInfo) { + pub fn insert_account(&mut self, address: Address, info: AccountInfo) { self.cache.insert_account(address, info) } pub fn insert_account_with_storage( &mut self, - address: B160, + address: Address, info: AccountInfo, storage: PlainStorage, ) { @@ -146,7 +146,7 @@ impl State { } /// Apply evm transitions to transition state. - fn apply_transition(&mut self, transitions: Vec<(B160, TransitionAccount)>) { + fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) { // add transition to transition state. if let Some(s) = self.transition_state.as_mut() { s.add_transitions(transitions) @@ -165,7 +165,7 @@ impl State { } } - pub fn load_cache_account(&mut self, address: B160) -> Result<&mut CacheAccount, DB::Error> { + pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> { match self.cache.accounts.entry(address) { hash_map::Entry::Vacant(entry) => { if self.use_preloaded_bundle { @@ -211,7 +211,7 @@ impl State { impl Database for State { type Error = DB::Error; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { self.load_cache_account(address).map(|a| a.account_info()) } @@ -238,7 +238,7 @@ impl Database for State { res } - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { // Account is guaranteed to be loaded. // Note that storage from bundle is already loaded with account. if let Some(account) = self.cache.accounts.get_mut(&address) { @@ -292,7 +292,7 @@ impl Database for State { } impl DatabaseCommit for State { - fn commit(&mut self, evm_state: HashMap) { + fn commit(&mut self, evm_state: HashMap) { let transitions = self.cache.apply_evm_state(evm_state); self.apply_transition(transitions); } @@ -345,7 +345,7 @@ mod tests { // Non-existing account for testing account state transitions. // [LoadedNotExisting] -> [Changed] (nonce: 1, balance: 1) -> [Changed] (nonce: 2) -> [Changed] (nonce: 3) - let new_account_address = B160::from_slice(&[0x1; 20]); + let new_account_address = Address::from_slice(&[0x1; 20]); let new_account_created_info = AccountInfo { nonce: 1, balance: U256::from(1), @@ -361,7 +361,7 @@ mod tests { }; // Existing account for testing storage state transitions. - let existing_account_address = B160::from_slice(&[0x2; 20]); + let existing_account_address = Address::from_slice(&[0x2; 20]); let existing_account_initial_info = AccountInfo { nonce: 1, ..Default::default() @@ -588,7 +588,7 @@ mod tests { let mut state = State::builder().with_bundle_update().build(); // Non-existing account. - let new_account_address = B160::from_slice(&[0x1; 20]); + let new_account_address = Address::from_slice(&[0x1; 20]); let new_account_created_info = AccountInfo { nonce: 1, balance: U256::from(1), @@ -596,7 +596,7 @@ mod tests { }; // Existing account. - let existing_account_address = B160::from_slice(&[0x2; 20]); + let existing_account_address = Address::from_slice(&[0x2; 20]); let existing_account_initial_info = AccountInfo { nonce: 1, ..Default::default() @@ -609,7 +609,7 @@ mod tests { // Existing account with storage. let (slot1, slot2) = (U256::from(1), U256::from(2)); - let existing_account_with_storage_address = B160::from_slice(&[0x3; 20]); + let existing_account_with_storage_address = Address::from_slice(&[0x3; 20]); let existing_account_with_storage_info = AccountInfo { nonce: 1, ..Default::default() @@ -730,7 +730,7 @@ mod tests { let mut state = State::builder().with_bundle_update().build(); // Existing account. - let existing_account_address = B160::from_slice(&[0x1; 20]); + let existing_account_address = Address::from_slice(&[0x1; 20]); let existing_account_info = AccountInfo { nonce: 1, ..Default::default() diff --git a/crates/revm/src/db/states/transition_state.rs b/crates/revm/src/db/states/transition_state.rs index f4d9829fcd..802a29c1ee 100644 --- a/crates/revm/src/db/states/transition_state.rs +++ b/crates/revm/src/db/states/transition_state.rs @@ -1,11 +1,11 @@ use super::TransitionAccount; use alloc::vec::Vec; -use revm_interpreter::primitives::{hash_map::Entry, HashMap, B160}; +use revm_interpreter::primitives::{hash_map::Entry, Address, HashMap}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct TransitionState { /// Block state account with account state - pub transitions: HashMap, + pub transitions: HashMap, } impl Default for TransitionState { @@ -19,7 +19,7 @@ impl Default for TransitionState { impl TransitionState { /// Create new transition state with one transition. - pub fn single(address: B160, transition: TransitionAccount) -> Self { + pub fn single(address: Address, transition: TransitionAccount) -> Self { let mut transitions = HashMap::new(); transitions.insert(address, transition); TransitionState { transitions } @@ -30,7 +30,7 @@ impl TransitionState { core::mem::take(self) } - pub fn add_transitions(&mut self, transitions: Vec<(B160, TransitionAccount)>) { + pub fn add_transitions(&mut self, transitions: Vec<(Address, TransitionAccount)>) { for (address, account) in transitions { match self.transitions.entry(address) { Entry::Occupied(entry) => { diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 98997d5ca2..577b219e3f 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -6,9 +6,9 @@ use crate::interpreter::{ }; use crate::journaled_state::{is_precompile, JournalCheckpoint}; use crate::primitives::{ - create2_address, create_address, keccak256, AnalysisKind, Bytecode, Bytes, EVMError, EVMResult, - Env, ExecutionResult, InvalidTransaction, Log, Output, ResultAndState, Spec, SpecId::*, - TransactTo, B160, B256, U256, + create2_address, create_address, keccak256, Address, AnalysisKind, Bytecode, Bytes, EVMError, + EVMResult, Env, ExecutionResult, InvalidTransaction, Log, Output, ResultAndState, Spec, + SpecId::*, TransactTo, B256, U256, }; use crate::{db::Database, journaled_state::JournaledState, precompile, Inspector}; use alloc::boxed::Box; @@ -41,14 +41,14 @@ pub struct EVMImpl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> { struct PreparedCreate { gas: Gas, - created_address: B160, + created_address: Address, checkpoint: JournalCheckpoint, contract: Box, } struct CreateResult { result: InstructionResult, - created_address: Option, + created_address: Option
, gas: Gas, return_value: Bytes, } @@ -101,7 +101,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, /// caller's balance directly after minting the requested amount of ETH. fn remove_l1_cost( is_deposit: bool, - tx_caller: B160, + tx_caller: Address, l1_cost: U256, db: &mut DB, journal: &mut JournaledState, @@ -134,7 +134,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, /// in wei to the caller's balance. This should be persisted to the database /// prior to the rest of execution. fn commit_mint_value( - tx_caller: B160, + tx_caller: Address, tx_mint: Option, db: &mut DB, journal: &mut JournaledState, @@ -842,7 +842,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host .ok() } - fn load_account(&mut self, address: B160) -> Option<(bool, bool)> { + fn load_account(&mut self, address: Address) -> Option<(bool, bool)> { self.data .journaled_state .load_account_exist(address, self.data.db) @@ -850,7 +850,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host .ok() } - fn balance(&mut self, address: B160) -> Option<(U256, bool)> { + fn balance(&mut self, address: Address) -> Option<(U256, bool)> { let db = &mut self.data.db; let journal = &mut self.data.journaled_state; let error = &mut self.data.error; @@ -861,7 +861,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host .map(|(acc, is_cold)| (acc.info.balance, is_cold)) } - fn code(&mut self, address: B160) -> Option<(Bytecode, bool)> { + fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> { let journal = &mut self.data.journaled_state; let db = &mut self.data.db; let error = &mut self.data.error; @@ -874,7 +874,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } /// Get code hash of address. - fn code_hash(&mut self, address: B160) -> Option<(B256, bool)> { + fn code_hash(&mut self, address: Address) -> Option<(B256, bool)> { let journal = &mut self.data.journaled_state; let db = &mut self.data.db; let error = &mut self.data.error; @@ -884,13 +884,13 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host .map_err(|e| *error = Some(e)) .ok()?; if acc.is_empty() { - return Some((B256::zero(), is_cold)); + return Some((B256::ZERO, is_cold)); } Some((acc.info.code_hash, is_cold)) } - fn sload(&mut self, address: B160, index: U256) -> Option<(U256, bool)> { + fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)> { // account is always warm. reference on that statement https://eips.ethereum.org/EIPS/eip-2929 see `Note 2:` self.data .journaled_state @@ -901,7 +901,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host fn sstore( &mut self, - address: B160, + address: Address, index: U256, value: U256, ) -> Option<(U256, U256, U256, bool)> { @@ -912,15 +912,15 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host .ok() } - fn tload(&mut self, address: B160, index: U256) -> U256 { + fn tload(&mut self, address: Address, index: U256) -> U256 { self.data.journaled_state.tload(address, index) } - fn tstore(&mut self, address: B160, index: U256, value: U256) { + fn tstore(&mut self, address: Address, index: U256, value: U256) { self.data.journaled_state.tstore(address, index, value) } - fn log(&mut self, address: B160, topics: Vec, data: Bytes) { + fn log(&mut self, address: Address, topics: Vec, data: Bytes) { if INSPECT { self.inspector.log(&mut self.data, &address, &topics, &data); } @@ -932,7 +932,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host self.data.journaled_state.log(log); } - fn selfdestruct(&mut self, address: B160, target: B160) -> Option { + fn selfdestruct(&mut self, address: Address, target: Address) -> Option { if INSPECT { let acc = self.data.journaled_state.state.get(&address).unwrap(); self.inspector @@ -948,7 +948,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host fn create( &mut self, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { // Call inspector if INSPECT { let (ret, address, gas, out) = self.inspector.create(&mut self.data, inputs); @@ -1007,7 +1007,7 @@ mod tests { #[test] fn test_commit_mint_value() { - let caller = B160::zero(); + let caller = Address::ZERO; let mint_value = Some(1u128); let mut db = InMemoryDB::default(); db.insert_account_info( @@ -1015,7 +1015,7 @@ mod tests { AccountInfo { nonce: 0, balance: U256::from(100), - code_hash: B256::zero(), + code_hash: B256::ZERO, code: None, }, ); @@ -1053,7 +1053,7 @@ mod tests { #[test] fn test_remove_l1_cost_non_deposit() { - let caller = B160::zero(); + let caller = Address::ZERO; let mut db = InMemoryDB::default(); let mut journal = JournaledState::new(0, SpecId::BERLIN); let slots = &[U256::from(100)]; @@ -1072,14 +1072,14 @@ mod tests { #[test] fn test_remove_l1_cost() { - let caller = B160::zero(); + let caller = Address::ZERO; let mut db = InMemoryDB::default(); db.insert_account_info( caller, AccountInfo { nonce: 0, balance: U256::from(100), - code_hash: B256::zero(), + code_hash: B256::ZERO, code: None, }, ); @@ -1103,14 +1103,14 @@ mod tests { #[test] fn test_remove_l1_cost_lack_of_funds() { - let caller = B160::zero(); + let caller = Address::ZERO; let mut db = InMemoryDB::default(); db.insert_account_info( caller, AccountInfo { nonce: 0, balance: U256::from(100), - code_hash: B256::zero(), + code_hash: B256::ZERO, code: None, }, ); diff --git a/crates/revm/src/handler/mainnet.rs b/crates/revm/src/handler/mainnet.rs index 81f12fdb6c..deaba88902 100644 --- a/crates/revm/src/handler/mainnet.rs +++ b/crates/revm/src/handler/mainnet.rs @@ -129,8 +129,7 @@ mod tests { let mut return_gas = Gas::new(90); return_gas.record_refund(30); - let gas = - handle_call_return::(&env, InstructionResult::Stop, return_gas.clone()); + let gas = handle_call_return::(&env, InstructionResult::Stop, return_gas); assert_eq!(gas.remaining(), 90); assert_eq!(gas.spend(), 10); assert_eq!(gas.refunded(), 30); diff --git a/crates/revm/src/handler/optimism.rs b/crates/revm/src/handler/optimism.rs index e71685f296..b178157683 100644 --- a/crates/revm/src/handler/optimism.rs +++ b/crates/revm/src/handler/optimism.rs @@ -177,7 +177,7 @@ mod tests { let mut env = Env::default(); env.tx.gas_limit = 100; env.cfg.optimism = true; - env.tx.optimism.source_hash = Some(B256::zero()); + env.tx.optimism.source_hash = Some(B256::ZERO); let gas = handle_call_return::(&env, InstructionResult::Stop, Gas::new(90)); assert_eq!(gas.remaining(), 90); @@ -190,13 +190,12 @@ mod tests { let mut env = Env::default(); env.tx.gas_limit = 100; env.cfg.optimism = true; - env.tx.optimism.source_hash = Some(B256::zero()); + env.tx.optimism.source_hash = Some(B256::ZERO); let mut ret_gas = Gas::new(90); ret_gas.record_refund(20); - let gas = - handle_call_return::(&env, InstructionResult::Stop, ret_gas.clone()); + let gas = handle_call_return::(&env, InstructionResult::Stop, ret_gas); assert_eq!(gas.remaining(), 90); assert_eq!(gas.spend(), 10); assert_eq!(gas.refunded(), 20); @@ -212,7 +211,7 @@ mod tests { let mut env = Env::default(); env.tx.gas_limit = 100; env.cfg.optimism = true; - env.tx.optimism.source_hash = Some(B256::zero()); + env.tx.optimism.source_hash = Some(B256::ZERO); let gas = handle_call_return::(&env, InstructionResult::Stop, Gas::new(90)); assert_eq!(gas.remaining(), 0); diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 9d0671953f..b1d20b9d70 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,6 +1,6 @@ use crate::evm_impl::EVMData; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}; -use crate::primitives::{db::Database, Bytes, B160, B256, U256}; +use crate::primitives::{db::Database, Address, Bytes, B256, U256}; use auto_impl::auto_impl; @@ -59,7 +59,7 @@ pub trait Inspector { fn log( &mut self, _evm_data: &mut EVMData<'_, DB>, - _address: &B160, + _address: &Address, _topics: &[B256], _data: &Bytes, ) { @@ -110,7 +110,7 @@ pub trait Inspector { &mut self, _data: &mut EVMData<'_, DB>, _inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { ( InstructionResult::Continue, None, @@ -128,13 +128,13 @@ pub trait Inspector { _data: &mut EVMData<'_, DB>, _inputs: &CreateInputs, ret: InstructionResult, - address: Option, + address: Option
, remaining_gas: Gas, out: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { (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) {} + fn selfdestruct(&mut self, _contract: Address, _target: Address, _value: U256) {} } diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index 44881be409..f0b8a4ae88 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -2,7 +2,7 @@ //! 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::primitives::{Address, Bytes, U256}; use crate::{inspectors::GasInspector, Database, EVMData, Inspector}; #[derive(Clone, Default)] pub struct CustomPrintTracer { @@ -74,10 +74,10 @@ impl Inspector for CustomPrintTracer { data: &mut EVMData<'_, DB>, inputs: &CreateInputs, ret: InstructionResult, - address: Option, + address: Option
, remaining_gas: Gas, out: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { self.gas_inspector .create_end(data, inputs, ret, address, remaining_gas, out.clone()); (ret, address, remaining_gas, out) @@ -103,19 +103,15 @@ impl Inspector for CustomPrintTracer { &mut self, _data: &mut EVMData<'_, DB>, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { println!( "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", - inputs.caller, - inputs.scheme, - inputs.value, - hex::encode(&inputs.init_code), - inputs.gas_limit + inputs.caller, inputs.scheme, inputs.value, inputs.init_code, inputs.gas_limit ); (InstructionResult::Continue, None, Gas::new(0), Bytes::new()) } - fn selfdestruct(&mut self, contract: B160, target: B160, value: U256) { + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { println!( "SELFDESTRUCT: contract: {:?}, refund target: {:?}, value {:?}", contract, target, value @@ -130,12 +126,13 @@ mod test { #[cfg(not(feature = "no_gas_measuring"))] #[cfg(not(feature = "optimism"))] fn gas_calculation_underflow() { - use crate::primitives::hex_literal; + use crate::primitives::{address, bytes}; + // https://github.com/bluealloy/revm/issues/277 // checks this use case let mut evm = crate::new(); let mut database = crate::InMemoryDB::default(); - let code: crate::primitives::Bytes = hex_literal::hex!("5b597fb075978b6c412c64d169d56d839a8fe01b3f4607ed603b2c78917ce8be1430fe6101e8527ffe64706ecad72a2f5c97a95e006e279dc57081902029ce96af7edae5de116fec610208527f9fc1ef09d4dd80683858ae3ea18869fe789ddc365d8d9d800e26c9872bac5e5b6102285260276102485360d461024953601661024a53600e61024b53607d61024c53600961024d53600b61024e5360b761024f5360596102505360796102515360a061025253607261025353603a6102545360fb61025553601261025653602861025753600761025853606f61025953601761025a53606161025b53606061025c5360a661025d53602b61025e53608961025f53607a61026053606461026153608c6102625360806102635360d56102645360826102655360ae61026653607f6101e8610146610220677a814b184591c555735fdcca53617f4d2b9134b29090c87d01058e27e962047654f259595947443b1b816b65cdb6277f4b59c10a36f4e7b8658f5a5e6f5561").to_vec().into(); + let code = bytes!("5b597fb075978b6c412c64d169d56d839a8fe01b3f4607ed603b2c78917ce8be1430fe6101e8527ffe64706ecad72a2f5c97a95e006e279dc57081902029ce96af7edae5de116fec610208527f9fc1ef09d4dd80683858ae3ea18869fe789ddc365d8d9d800e26c9872bac5e5b6102285260276102485360d461024953601661024a53600e61024b53607d61024c53600961024d53600b61024e5360b761024f5360596102505360796102515360a061025253607261025353603a6102545360fb61025553601261025653602861025753600761025853606f61025953601761025a53606161025b53606061025c5360a661025d53602b61025e53608961025f53607a61026053606461026153608c6102625360806102635360d56102645360826102655360ae61026653607f6101e8610146610220677a814b184591c555735fdcca53617f4d2b9134b29090c87d01058e27e962047654f259595947443b1b816b65cdb6277f4b59c10a36f4e7b8658f5a5e6f5561"); let acc_info = crate::primitives::AccountInfo { balance: "0x100c5d668240db8e00".parse().unwrap(), @@ -143,14 +140,11 @@ mod test { code: Some(crate::primitives::Bytecode::new_raw(code.clone())), nonce: 1, }; - let callee = hex_literal::hex!("5fdcca53617f4d2b9134b29090c87d01058e27e9"); - database.insert_account_info(crate::primitives::B160(callee), acc_info); + let callee = address!("5fdcca53617f4d2b9134b29090c87d01058e27e9"); + database.insert_account_info(callee, acc_info); evm.database(database); - evm.env.tx.caller = crate::primitives::B160(hex_literal::hex!( - "5fdcca53617f4d2b9134b29090c87d01058e27e0" - )); - evm.env.tx.transact_to = - crate::primitives::TransactTo::Call(crate::primitives::B160(callee)); + evm.env.tx.caller = address!("5fdcca53617f4d2b9134b29090c87d01058e27e0"); + evm.env.tx.transact_to = crate::primitives::TransactTo::Call(callee); evm.env.tx.data = crate::primitives::Bytes::new(); evm.env.tx.value = crate::primitives::U256::ZERO; let _ = evm.inspect_commit(super::CustomPrintTracer::default()); diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index fa19c7699d..628137a9d6 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -1,7 +1,7 @@ //! GasIspector. Helper Inspector to calculate gas for others. -//! + use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult}; -use crate::primitives::{db::Database, Bytes, B160}; +use crate::primitives::{db::Database, Address, Bytes}; use crate::{evm_impl::EVMData, Inspector}; #[allow(dead_code)] @@ -83,10 +83,10 @@ impl Inspector for GasInspector { _data: &mut EVMData<'_, DB>, _inputs: &CreateInputs, ret: InstructionResult, - address: Option, + address: Option
, remaining_gas: Gas, out: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { (ret, address, remaining_gas, out) } } @@ -94,7 +94,7 @@ impl Inspector for GasInspector { #[cfg(test)] mod tests { use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}; - use crate::primitives::{Bytes, B160, B256}; + use crate::primitives::{Address, Bytes, B256}; use crate::{inspectors::GasInspector, Database, EVMData, Inspector}; #[derive(Default, Debug)] @@ -127,7 +127,7 @@ mod tests { fn log( &mut self, evm_data: &mut EVMData<'_, DB>, - address: &B160, + address: &Address, topics: &[B256], data: &Bytes, ) { @@ -177,7 +177,7 @@ mod tests { &mut self, data: &mut EVMData<'_, DB>, call: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { self.gas_inspector.create(data, call); ( @@ -193,10 +193,10 @@ mod tests { data: &mut EVMData<'_, DB>, inputs: &CreateInputs, status: InstructionResult, - address: Option, + address: Option
, gas: Gas, retdata: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { self.gas_inspector .create_end(data, inputs, status, address, gas, retdata.clone()); (status, address, gas, retdata) @@ -208,9 +208,7 @@ mod tests { fn test_gas_inspector() { use crate::db::BenchmarkDB; use crate::interpreter::{opcode, OpCode}; - use crate::primitives::{ - hex_literal::hex, Bytecode, Bytes, ResultAndState, TransactTo, B160, - }; + use crate::primitives::{address, Bytecode, Bytes, ResultAndState, TransactTo}; let contract_data: Bytes = Bytes::from(vec![ opcode::PUSH1, @@ -231,9 +229,9 @@ mod tests { let mut evm = crate::new(); evm.database(BenchmarkDB::new_bytecode(bytecode.clone())); - evm.env.tx.caller = B160(hex!("1000000000000000000000000000000000000000")); + evm.env.tx.caller = address!("1000000000000000000000000000000000000000"); evm.env.tx.transact_to = - TransactTo::Call(B160(hex!("0000000000000000000000000000000000000000"))); + TransactTo::Call(address!("0000000000000000000000000000000000000000")); evm.env.tx.gas_limit = 21100; let mut inspector = StackInspector::default(); diff --git a/crates/revm/src/inspector/tracer_eip3155.rs b/crates/revm/src/inspector/tracer_eip3155.rs index cd8ff0f3b8..5625225f40 100644 --- a/crates/revm/src/inspector/tracer_eip3155.rs +++ b/crates/revm/src/inspector/tracer_eip3155.rs @@ -2,7 +2,7 @@ use crate::inspectors::GasInspector; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult}; -use crate::primitives::{db::Database, hex, Bytes, B160}; +use crate::primitives::{db::Database, hex, Address, Bytes}; use crate::{evm_impl::EVMData, Inspector}; use revm_interpreter::primitives::U256; use revm_interpreter::{opcode, Interpreter, Memory, Stack}; @@ -124,7 +124,7 @@ impl Inspector for TracerEip3155 { &mut self, data: &mut EVMData<'_, DB>, _inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { self.print_log_line(data.journaled_state.depth()); ( InstructionResult::Continue, @@ -139,10 +139,10 @@ impl Inspector for TracerEip3155 { data: &mut EVMData<'_, DB>, inputs: &CreateInputs, ret: InstructionResult, - address: Option, + address: Option
, remaining_gas: Gas, out: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { self.gas_inspector .create_end(data, inputs, ret, address, remaining_gas, out.clone()); self.skip = true; @@ -176,9 +176,8 @@ impl TracerEip3155 { } fn short_hex(b: U256) -> String { - let s = hex::encode(b.to_be_bytes_vec()) - .trim_start_matches('0') - .to_string(); + let s = hex::encode(b.to_be_bytes::<32>()); + let s = s.trim_start_matches('0'); if s.is_empty() { "0x0".to_string() } else { diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index 8e8c9c1d77..03901e4ba0 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -1,7 +1,7 @@ use crate::interpreter::{inner_models::SelfDestructResult, InstructionResult}; use crate::primitives::{ - db::Database, hash_map::Entry, Account, Bytecode, HashMap, Log, Spec, SpecId::*, State, - StorageSlot, TransientStorage, B160, KECCAK_EMPTY, PRECOMPILE3, U256, + db::Database, hash_map::Entry, Account, Address, Bytecode, HashMap, Log, Spec, SpecId::*, + State, StorageSlot, TransientStorage, KECCAK_EMPTY, PRECOMPILE3, U256, }; use alloc::vec::Vec; use core::mem; @@ -35,13 +35,13 @@ pub enum JournalEntry { /// Used to mark account that is warm inside EVM in regards to EIP-2929 AccessList. /// Action: We will add Account to state. /// Revert: we will remove account from state. - AccountLoaded { address: B160 }, + AccountLoaded { address: Address }, /// Mark account to be destroyed and journal balance to be reverted /// Action: Mark account and transfer the balance /// Revert: Unmark the account and transfer balance back AccountDestroyed { - address: B160, - target: B160, + address: Address, + target: Address, was_destroyed: bool, // if account had already been destroyed before this journal entry had_balance: U256, }, @@ -49,27 +49,31 @@ pub enum JournalEntry { /// Only when account is called (to execute contract or transfer balance) only then account is made touched. /// Action: Mark account touched /// Revert: Unmark account touched - AccountTouched { address: B160 }, + AccountTouched { address: Address }, /// Transfer balance between two accounts /// Action: Transfer balance /// Revert: Transfer balance back - BalanceTransfer { from: B160, to: B160, balance: U256 }, + BalanceTransfer { + from: Address, + to: Address, + balance: U256, + }, /// Increment nonce /// Action: Increment nonce by one /// Revert: Decrement nonce by one NonceChange { - address: B160, //geth has nonce value, + address: Address, //geth has nonce value, }, /// Create account: /// Actions: Mark account as created /// Revert: Unmart account as created and reset nonce to zero. - AccountCreated { address: B160 }, + AccountCreated { address: Address }, /// It is used to track both storage change and warm load of storage slot. For warm load in regard /// to EIP-2929 AccessList had_value will be None /// Action: Storage change or warm load /// Revert: Revert to previous value or remove slot from storage StorageChange { - address: B160, + address: Address, key: U256, had_value: Option, //if none, storage slot was cold loaded from db and needs to be removed }, @@ -77,14 +81,14 @@ pub enum JournalEntry { /// Action: Transient storage changed. /// Revert: Revert to previous value. TransientStorageChange { - address: B160, + address: Address, key: U256, had_value: U256, }, /// Code changed /// Action: Account code changed /// Revert: Revert to previous bytecode. - CodeChange { address: B160 }, + CodeChange { address: Address }, } /// SubRoutine checkpoint that will help us to go back from this @@ -121,13 +125,13 @@ impl JournaledState { /// Mark account as touched as only touched accounts will be added to state. /// This is especially important for state clear where touched empty accounts needs to /// be removed from state. - pub fn touch(&mut self, address: &B160) { + pub fn touch(&mut self, address: &Address) { if let Some(account) = self.state.get_mut(address) { Self::touch_account(self.journal.last_mut().unwrap(), address, account); } } - fn touch_account(journal: &mut Vec, address: &B160, account: &mut Account) { + fn touch_account(journal: &mut Vec, address: &Address, account: &mut Account) { if !account.is_touched() { journal.push(JournalEntry::AccountTouched { address: *address }); account.mark_touch(); @@ -145,7 +149,7 @@ impl JournaledState { } /// Use it with load_account function. - pub fn account(&self, address: B160) -> &Account { + pub fn account(&self, address: Address) -> &Account { self.state.get(&address).unwrap() // Always assume that acc is already loaded } @@ -155,7 +159,7 @@ impl JournaledState { /// use it only if you know that acc is warm /// Assume account is warm - pub fn set_code(&mut self, address: B160, code: Bytecode) { + pub fn set_code(&mut self, address: Address, code: Bytecode) { let account = self.state.get_mut(&address).unwrap(); Self::touch_account(self.journal.last_mut().unwrap(), &address, account); @@ -168,7 +172,7 @@ impl JournaledState { account.info.code = Some(code); } - pub fn inc_nonce(&mut self, address: B160) -> Option { + pub fn inc_nonce(&mut self, address: Address) -> Option { let account = self.state.get_mut(&address).unwrap(); // Check if nonce is going to overflow. if account.info.nonce == u64::MAX { @@ -187,8 +191,8 @@ impl JournaledState { pub fn transfer( &mut self, - from: &B160, - to: &B160, + from: &Address, + to: &Address, balance: U256, db: &mut DB, ) -> Result<(), InstructionResult> { @@ -243,8 +247,8 @@ impl JournaledState { /// caller is already loaded inside evm. This is already done inside `create_inner` pub fn create_account_checkpoint( &mut self, - caller: B160, - address: B160, + caller: Address, + address: Address, balance: U256, ) -> Result { // Enter subroutine @@ -310,7 +314,7 @@ impl JournaledState { #[inline(always)] pub fn check_account_collision( - address: B160, + address: Address, account: &Account, num_of_precompiles: usize, ) -> bool { @@ -472,8 +476,8 @@ impl JournaledState { /// * https://eips.ethereum.org/EIPS/eip-6780 pub fn selfdestruct( &mut self, - address: B160, - target: B160, + address: Address, + target: Address, db: &mut DB, ) -> Result { let (is_cold, target_exists) = self.load_account_exist(target, db)?; @@ -532,7 +536,7 @@ impl JournaledState { pub fn initial_account_and_code_load( &mut self, - address: B160, + address: Address, db: &mut DB, ) -> Result<&mut Account, DB::Error> { let account = self.initial_account_load(address, &[], db)?; @@ -551,7 +555,7 @@ impl JournaledState { /// Initial load of account. This load will not be tracked inside journal pub fn initial_account_load( &mut self, - address: B160, + address: Address, slots: &[U256], db: &mut DB, ) -> Result<&mut Account, DB::Error> { @@ -577,7 +581,7 @@ impl JournaledState { /// load account into memory. return if it is cold or warm accessed pub fn load_account( &mut self, - address: B160, + address: Address, db: &mut DB, ) -> Result<(&mut Account, bool), DB::Error> { Ok(match self.state.entry(address) { @@ -606,7 +610,7 @@ impl JournaledState { // first is is_cold second bool is exists. pub fn load_account_exist( &mut self, - address: B160, + address: Address, db: &mut DB, ) -> Result<(bool, bool), DB::Error> { let is_spurious_dragon_enabled = SpecId::enabled(self.spec, SPURIOUS_DRAGON); @@ -624,7 +628,7 @@ impl JournaledState { pub fn load_code( &mut self, - address: B160, + address: Address, db: &mut DB, ) -> Result<(&mut Account, bool), DB::Error> { let (acc, is_cold) = self.load_account(address, db)?; @@ -643,7 +647,7 @@ impl JournaledState { // account is already present and loaded. pub fn sload( &mut self, - address: B160, + address: Address, key: U256, db: &mut DB, ) -> Result<(U256, bool), DB::Error> { @@ -681,7 +685,7 @@ impl JournaledState { /// returns (original,present,new) slot pub fn sstore( &mut self, - address: B160, + address: Address, key: U256, new: U256, db: &mut DB, @@ -714,7 +718,7 @@ impl JournaledState { /// Read transient storage tied to the account. /// /// EIP-1153: Transient storage opcodes - pub fn tload(&mut self, address: B160, key: U256) -> U256 { + pub fn tload(&mut self, address: Address, key: U256) -> U256 { self.transient_storage .get(&(address, key)) .copied() @@ -727,7 +731,7 @@ impl JournaledState { /// so that old state can be reverted if that action is needed. /// /// EIP-1153: Transient storage opcodes - pub fn tstore(&mut self, address: B160, key: U256, new: U256) { + pub fn tstore(&mut self, address: Address, key: U256, new: U256) { let had_value = if new == U256::ZERO { // if new values is zero, remove entry from transient storage. // if previous values was some insert it inside journal. @@ -771,7 +775,7 @@ impl JournaledState { /// Check if address is precompile by having assumption /// that precompiles are in range of 1 to N. #[inline(always)] -pub fn is_precompile(address: B160, num_of_precompiles: usize) -> bool { +pub fn is_precompile(address: Address, num_of_precompiles: usize) -> bool { if !address[..18].iter().all(|i| *i == 0) { return false; } @@ -787,7 +791,7 @@ mod test { fn test_is_precompile() { assert!( !is_precompile( - B160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3 ), "Zero is not precompile" @@ -795,7 +799,7 @@ mod test { assert!( !is_precompile( - B160([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9]), + Address::new([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9]), 3 ), "0x100..0 is not precompile" @@ -803,7 +807,7 @@ mod test { assert!( !is_precompile( - B160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]), + Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]), 3 ), "0x000..4 is not precompile" @@ -811,7 +815,7 @@ mod test { assert!( is_precompile( - B160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), + Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]), 3 ), "0x00..01 is precompile" @@ -819,7 +823,7 @@ mod test { assert!( is_precompile( - B160([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]), + Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]), 3 ), "0x000..3 is precompile" diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 0770d0325c..fbaeab6c18 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(unreachable_pub)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] #[macro_use] extern crate alloc; diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index e33d1d8eff..09323d8a25 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -1,9 +1,7 @@ //! Optimism-specific constants, types, and helpers. +use crate::primitives::{address, db::Database, Address, Bytes, Spec, SpecId, U256}; use core::ops::Mul; -use revm_interpreter::primitives::{ - db::Database, hex_literal::hex, Bytes, Spec, SpecId, B160, U256, -}; const ZERO_BYTE_COST: u64 = 4; const NON_ZERO_BYTE_COST: u64 = 16; @@ -13,13 +11,13 @@ const L1_OVERHEAD_SLOT: U256 = U256::from_limbs([5u64, 0, 0, 0]); const L1_SCALAR_SLOT: U256 = U256::from_limbs([6u64, 0, 0, 0]); /// The address of L1 fee recipient. -pub const L1_FEE_RECIPIENT: B160 = B160(hex!("420000000000000000000000000000000000001A")); +pub const L1_FEE_RECIPIENT: Address = address!("420000000000000000000000000000000000001A"); /// The address of the base fee recipient. -pub const BASE_FEE_RECIPIENT: B160 = B160(hex!("4200000000000000000000000000000000000019")); +pub const BASE_FEE_RECIPIENT: Address = address!("4200000000000000000000000000000000000019"); /// The address of the L1Block contract. -pub const L1_BLOCK_CONTRACT: B160 = B160(hex!("4200000000000000000000000000000000000015")); +pub const L1_BLOCK_CONTRACT: Address = address!("4200000000000000000000000000000000000015"); /// L1 block info /// @@ -104,7 +102,7 @@ impl L1BlockInfo { #[cfg(test)] mod tests { use super::*; - use crate::primitives::specification::*; + use crate::primitives::{bytes, specification::*}; #[test] fn test_data_gas_non_zero_bytes() { @@ -120,7 +118,7 @@ mod tests { // Pre-regolith (ie bedrock) has an extra 68 non-zero bytes // gas cost = 3 non-zero bytes * NON_ZERO_BYTE_COST + NON_ZERO_BYTE_COST * 68 // gas cost = 3 * 16 + 68 * 16 = 1136 - let input = Bytes::from(hex!("FACADE").to_vec()); + let input = bytes!("FACADE"); let bedrock_data_gas = l1_block_info.data_gas::(&input); assert_eq!(bedrock_data_gas, U256::from(1136)); @@ -144,7 +142,7 @@ mod tests { // Pre-regolith (ie bedrock) has an extra 68 non-zero bytes // gas cost = 3 non-zero * NON_ZERO_BYTE_COST + 2 * ZERO_BYTE_COST + NON_ZERO_BYTE_COST * 68 // gas cost = 3 * 16 + 2 * 4 + 68 * 16 = 1144 - let input = Bytes::from(hex!("FA00CA00DE").to_vec()); + let input = bytes!("FA00CA00DE"); let bedrock_data_gas = l1_block_info.data_gas::(&input); assert_eq!(bedrock_data_gas, U256::from(1144)); @@ -163,7 +161,7 @@ mod tests { }; // The gas cost here should be zero since the tx is a deposit - let input = Bytes::from(hex!("FACADE").to_vec()); + let input = bytes!("FACADE"); let gas_cost = l1_block_info.calculate_tx_l1_cost::(&input, true); assert_eq!(gas_cost, U256::ZERO); @@ -171,7 +169,7 @@ mod tests { assert_eq!(gas_cost, U256::from(1048)); // Zero rollup data gas cost should result in zero for non-deposits - let input = Bytes::from(hex!("").to_vec()); + let input = bytes!(""); let gas_cost = l1_block_info.calculate_tx_l1_cost::(&input, false); assert_eq!(gas_cost, U256::ZERO); } diff --git a/documentation/bins/revm-test.md b/documentation/bins/revm-test.md deleted file mode 100644 index 2757b53d14..0000000000 --- a/documentation/bins/revm-test.md +++ /dev/null @@ -1 +0,0 @@ -# revm-test diff --git a/documentation/bins/revme.md b/documentation/bins/revme.md deleted file mode 100644 index 15bca4c3fd..0000000000 --- a/documentation/bins/revme.md +++ /dev/null @@ -1 +0,0 @@ -# revme diff --git a/documentation/src/crates/interpreter/inner_models.md b/documentation/src/crates/interpreter/inner_models.md index daaacc21d6..7524d94263 100644 --- a/documentation/src/crates/interpreter/inner_models.md +++ b/documentation/src/crates/interpreter/inner_models.md @@ -22,8 +22,8 @@ The `inner_models.rs` module within this Rust EVM implementation encompasses a c - `Transfer` Struct - The `Transfer` struct represents a value transfer between two accounts. +The `Transfer` struct represents a value transfer between two accounts. - `SelfDestructResult` Struct - The `SelfDestructResult` struct captures the result of a self-destruction operation on a contract. In summary, the `inner_models.rs` module provides several crucial data structures that facilitate the representation and handling of various EVM operations and their associated data within this Rust EVM implementation. \ No newline at end of file +Finally, the `SelfDestructResult` struct captures the result of a self-destruction operation on a contract. In summary, the `inner_models.rs` module provides several crucial data structures that facilitate the representation and handling of various EVM operations and their associated data within this Rust EVM implementation. diff --git a/documentation/src/crates/precompile.md b/documentation/src/crates/precompile.md index cae13c8f50..334594cfe9 100644 --- a/documentation/src/crates/precompile.md +++ b/documentation/src/crates/precompile.md @@ -13,7 +13,7 @@ Modules: Types and Constants: -- `B160`: A type alias for an array of 20 bytes. This is typically used to represent Ethereum addresses. +- `Address`: A type alias for an array of 20 bytes. This is typically used to represent Ethereum addresses. - `B256`: A type alias for an array of 32 bytes, typically used to represent 256-bit hashes or integer values in Ethereum. - `PrecompileOutput`: Represents the output of a precompiled contract execution, including the gas cost, output data, and any logs generated. - `Log`: Represents an Ethereum log, with an address, a list of topics, and associated data. diff --git a/documentation/src/crates/primitives.md b/documentation/src/crates/primitives.md index 6a66639b77..027d4a6bd6 100644 --- a/documentation/src/crates/primitives.md +++ b/documentation/src/crates/primitives.md @@ -4,7 +4,7 @@ This crate is a core component of the Revm system. It is designed to provide def Modules: -- [bits](./primitives/bits.md): This module provides types for handling specific sizes of byte arrays (B160 and B256). +- [bits](./primitives/bits.md): This module provides types for handling specific sizes of byte arrays (Address and B256). - [bytecode](./primitives/bytecode.md): This module provides functionality related to EVM bytecode. - [constants](./primitives/constants.md): This module contains constant values used throughout the EVM implementation. - [db](./primitives/database.md): This module contains data structures and functions related to the EVM's database implementation. @@ -28,12 +28,11 @@ External Crates: Type Aliases: -- Address: An alias for B160, representing a 20-byte Ethereum address. - Hash: An alias for B256, typically used to represent 256-bit hashes or integer values in Ethereum. Re-exported Types: -- B160: A type representing a 160-bit (or 20-byte) array, typically used for Ethereum addresses. +- Address: A type representing a 160-bit (or 20-byte) array, typically used for Ethereum addresses. - B256: A type representing a 256-bit (or 32-byte) array, typically used for Ethereum hashes or integers. - Bytes: A type representing a sequence of bytes. - U256: A 256-bit unsigned integer type from the ruint crate. diff --git a/documentation/src/crates/primitives/bits.md b/documentation/src/crates/primitives/bits.md index e30b1d9e24..6378c0730a 100644 --- a/documentation/src/crates/primitives/bits.md +++ b/documentation/src/crates/primitives/bits.md @@ -1,13 +1,17 @@ # Bits -This module houses the definitions for fixed-size bit arrays, `B160` and `B256`, to represent 256-bit and 160-bit fixed-size hashes respectively. These are defined using the `construct_fixed_hash!` macro from the `fixed_hash` crate. +> NOTE: This module's types have been replaced by [`alloy_primitives`](https://github.com/alloy-rs/core)'s `Address` and `FixedBytes`. + +This module houses the definitions for fixed-size bit arrays, `Address` and `B256`, showcasing its role in managing bits-related operations, to represent 256-bit and 160-bit fixed-size hashes respectively. These are defined using the `construct_fixed_hash!` macro from the `fixed_hash` crate. The `AsRef` and `Deref` traits from `derive_more` crate are derived for both of these structures, providing convenient methods for converting these types to and from references of their underlying data. The `Arbitrary` trait from the `arbitrary` crate and the `PropTestArbitrary` trait from `proptest_derive` crate are derived conditionally when either testing or the "arbitrary" feature is enabled. -The module provides conversions between `B256`, `B160` and various other types such as `u64`, `primitive_types::H256`, `primitive_types::H160`, `primitive_types::U256`, and `ruint::aliases::U256`. The `impl` From blocks specify how to convert from one type to another. +The code also provides conversions between `B256`, `Address` and various other types such as `u64`, `primitive_types::H256`, `primitive_types::H160`, `primitive_types::U256`, and `ruint::aliases::U256`. The `impl` From blocks specify how to convert from one type to another. + +`impl_fixed_hash_conversions!` macro is used to define conversions between `B256` and `Address` types. -`impl_fixed_hash_conversions!` macro is used to define conversions between `B256` and `B160` types. +If the "serde" feature is enabled, the Serialize and Deserialize traits from the serde crate are implemented for `B256` and `Address` using a custom serialization method that outputs/reads these types as hexadecimal strings. This includes a custom serialization/deserialization module for handling hexadecimal data. -If the "serde" feature is enabled, the Serialize and Deserialize traits from the serde crate are implemented for `B256` and `B160` using a custom serialization method that outputs/reads these types as hexadecimal strings. This includes a custom serialization/deserialization module for handling hexadecimal data. +This module (serialize) provides functionality to serialize a slice of bytes to a hexadecimal string, and deserialize a hexadecimal string to a byte vector with size checks. It handles both "0x" prefixed and non-prefixed hexadecimal strings. It also provides functions to convert raw bytes to hexadecimal strings and vice versa, handling potential errors related to non-hexadecimal characters. The module also defines the `ExpectedLen` enum which is used to specify the expected length of the byte vectors during deserialization. diff --git a/documentation/src/crates/primitives/database.md b/documentation/src/crates/primitives/database.md index e28e08cd30..bf7fbbfeee 100644 --- a/documentation/src/crates/primitives/database.md +++ b/documentation/src/crates/primitives/database.md @@ -5,7 +5,7 @@ The module defines three primary traits (`Database`, `DatabaseCommit`, and `Data The `Database` trait defines an interface for mutable interaction with the database. It has a generic associated type `Error` to handle different kinds of errors that might occur during these interactions. It provides methods to retrieve basic account information (`basic`), retrieve account code by its hash (`code_by_hash`), retrieve the storage value of an address at a certain index (`storage`), and retrieve the block hash for a certain block number (`block_hash`). -The `DatabaseCommit` trait defines a single `commit` method for committing changes to the database. The changes are a map between Ethereum-like addresses (type `B160`) and accounts. +The `DatabaseCommit` trait defines a single `commit` method for committing changes to the database. The changes are a map between Ethereum-like addresses (type `Address`) and accounts. The `DatabaseRef` trait is similar to the `Database` trait but is designed for read-only or immutable interactions. It has the same `Error` associated type and the same set of methods as `Database`, but these methods take `&self` instead of `&mut self`, indicating that they do not mutate the database. diff --git a/documentation/src/crates/primitives/log.md b/documentation/src/crates/primitives/log.md index f24e319939..6bd7bcc1e9 100644 --- a/documentation/src/crates/primitives/log.md +++ b/documentation/src/crates/primitives/log.md @@ -2,7 +2,7 @@ This piece of Rust code defines a structure called Log which represents an Ethereum log entry. These logs are integral parts of the Ethereum network and are typically produced by smart contracts during execution. Each Log has three components: -- `address`: This field represents the address of the log originator, typically the smart contract that generated the log. The `B160` data type signifies a 160-bit Ethereum address. +- `address`: This field represents the address of the log originator, typically the smart contract that generated the log. The `Address` data type signifies a 160-bit Ethereum address. - `topics`: This field is a vector of `B256` type. In Ethereum, logs can have multiple '`topics`'. These are events that can be used to categorize and filter logs. The `B256` type denotes a 256-bit hash, which corresponds to the size of a topic in Ethereum. diff --git a/documentation/src/crates/primitives/state.md b/documentation/src/crates/primitives/state.md index ce6cc83c4e..d12a86f001 100644 --- a/documentation/src/crates/primitives/state.md +++ b/documentation/src/crates/primitives/state.md @@ -10,6 +10,6 @@ The `AccountStatus` is a set of bitflags, representing the state of the account. The `StorageSlot` struct represents a storage slot in the Ethereum Virtual Machine. It holds an `original_value` and a `present_value` and includes methods for creating a new slot and checking if the slot's value has been modified. -Two `HashMap` type aliases are created: `State` and `Storage`. `State` maps from a `B160` address to an `Account` and `Storage` maps from a `U256` key to a `StorageSlot`. +Two `HashMap` type aliases are created: `State` and `Storage`. `State` maps from a `Address` address to an `Account` and `Storage` maps from a `U256` key to a `StorageSlot`. The module includes a series of methods implemented for `Account` to manipulate and query the account's status. These include methods like `mark_selfdestruct`, `unmark_selfdestruct`, `is_selfdestructed`, `mark_touch`, `unmark_touch`, `is_touched`, `mark_created`, `is_newly_created`, `is_empty`, and `new_not_existing`. diff --git a/documentation/src/crates/primitives/utils.md b/documentation/src/crates/primitives/utils.md index bd6a1261ae..9bce3a6924 100644 --- a/documentation/src/crates/primitives/utils.md +++ b/documentation/src/crates/primitives/utils.md @@ -9,5 +9,3 @@ The `keccak256` function takes a byte slice input and returns its Keccak-256 has `create_address` function implements the address calculation for the Ethereum `CREATE` operation. It takes as parameters the address of the caller (`caller`) and a nonce (`nonce`). The function serializes these inputs using Recursive Length Prefix (RLP) encoding, calculates the Keccak-256 hash of the result, and returns the last 20 bytes of this hash as the created address. `create2_address` function implements the address calculation for the Ethereum `CREATE2` operation. It takes as parameters the address of the caller (`caller`), a hash of the initializing code (`code_hash`), and a "salt" value (`salt`). The function hashes these inputs together in a specific way, as per the Ethereum `CREATE2` rules, and returns the last 20 bytes of the result as the created address. - -The `serde_hex_bytes` module includes helper functions for serialization and deserialization of hexadecimal strings representing byte arrays. These functions will be used if the "serde" feature flag is enabled. serialize `function` converts a byte array into a hexadecimal string, while `deserialize` function does the reverse, converting a hexadecimal string back into a byte array. diff --git a/documentation/src/crates/revm/evm_impl.md b/documentation/src/crates/revm/evm_impl.md index 2aa388b4bc..afb0a0ee99 100644 --- a/documentation/src/crates/revm/evm_impl.md +++ b/documentation/src/crates/revm/evm_impl.md @@ -32,4 +32,4 @@ This module implements the Ethereum Virtual Machine (EVM), a stack-based virtual - `inputs`: A mutable reference to a `CallInputs` instance, which contains all the necessary information for the contract call. - The method returns a tuple containing the result of the call (as an `InstructionResult`), the remaining gas (as a `Gas` instance), and any output data from the call (as a `Bytes` instance). \ No newline at end of file + The method returns a tuple containing the result of the call (as an `InstructionResult`), the remaining gas (as a `Gas` instance), and any output data from the call (as a `Bytes` instance). diff --git a/examples/fork_ref_transact.rs b/examples/fork_ref_transact.rs index 6dcd4dade1..8abcacfd5c 100644 --- a/examples/fork_ref_transact.rs +++ b/examples/fork_ref_transact.rs @@ -1,17 +1,15 @@ -use anyhow::{Ok, Result}; -use bytes::Bytes; use ethers_contract::BaseContract; use ethers_core::abi::parse_abi; use ethers_providers::{Http, Provider}; use revm::{ db::{CacheDB, EmptyDB, EthersDB}, - primitives::{ExecutionResult, Output, TransactTo, B160, U256 as rU256}, + primitives::{address, ExecutionResult, Output, TransactTo, U256}, Database, EVM, }; -use std::{str::FromStr, sync::Arc}; +use std::sync::Arc; #[tokio::main] -async fn main() -> Result<()> { +async fn main() -> anyhow::Result<()> { // create ethers client and wrap it in Arc let client = Provider::::try_from( "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27", @@ -31,10 +29,10 @@ async fn main() -> Result<()> { // =========================================================== // // choose slot of storage that you would like to transact with - let slot = rU256::from(8); + let slot = U256::from(8); // ETH/USDT pair on Uniswap V2 - let pool_address = B160::from_str("0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852")?; + let pool_address = address!("0d4a11d5EEaaC28EC3F61d100daF4d40471f1852"); // generate abi for the calldata from the human readable interface let abi = BaseContract::from( @@ -74,13 +72,13 @@ async fn main() -> Result<()> { // fill in missing bits of env struct // change that to whatever caller you want to be - evm.env.tx.caller = B160::from_str("0x0000000000000000000000000000000000000000")?; + evm.env.tx.caller = address!("0000000000000000000000000000000000000000"); // account you want to transact with evm.env.tx.transact_to = TransactTo::Call(pool_address); // calldata formed via abigen - evm.env.tx.data = Bytes::from(hex::decode(hex::encode(&encoded))?); + evm.env.tx.data = encoded.0.into(); // transaction value in wei - evm.env.tx.value = rU256::from(0); + evm.env.tx.value = U256::from(0); // execute transaction without writing to the DB let ref_tx = evm.transact_ref().unwrap();