From 1139793d4583905e04d319e00d043d192103ab22 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Fri, 15 Mar 2024 17:12:52 +0100 Subject: [PATCH 01/33] Try to call revm directly --- .gitignore | 1 + Cargo.lock | 1 + Cargo.toml | 2 +- pyrevm.pyi | 38 +++-- pytest/test.py | 13 +- src/evm.rs | 327 ++++++++++++++++++++++++++++--------------- src/types/evm_env.rs | 30 ++++ 7 files changed, 281 insertions(+), 131 deletions(-) diff --git a/.gitignore b/.gitignore index 6594403..45e80d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ **/__pycache__/ +.idea/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 7c00834..a7471ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3953,6 +3953,7 @@ dependencies = [ "revm", "revm-interpreter", "ruint", + "tracing", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b67cc21..cd2f486 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,6 @@ crate-type = ["cdylib"] foundry-evm = { git = "https://github.com/foundry-rs/foundry", rev = "0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" } revm = "6.1" revm-interpreter = "=3.1" +tracing = "0.1" pyo3 = { version = "0.19", features = ["extension-module"] } - ruint = { version = "1.10", features = ["pyo3"] } diff --git a/pyrevm.pyi b/pyrevm.pyi index 20c3e27..b80bad9 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -15,6 +15,21 @@ class BlockEnv: gas_limit: Optional[int] = None, ) -> "BlockEnv": ... + @property + def number(self: "BlockEnv") -> int: ... + @property + def coinbase(self: "BlockEnv") -> str: ... + @property + def timestamp(self: "BlockEnv") -> int: ... + @property + def difficulty(self: "BlockEnv") -> int: ... + @property + def prevrandao(self: "BlockEnv") -> bytes: ... + @property + def basefee(self: "BlockEnv") -> int: ... + @property + def gas_limit(self: "BlockEnv") -> int: ... + class TxEnv: def __new__( cls: Type["TxEnv"], @@ -24,7 +39,7 @@ class TxEnv: gas_priority_fee: Optional[int] = None, to: Optional[str] = None, value: Optional[int] = None, - data: Optional[list[int]] = None, + data: Optional[bytes] = None, chain_id: Optional[int] = None, nonce: Optional[int] = None, ) -> "TxEnv": ... @@ -43,14 +58,14 @@ class AccountInfo: @property def nonce(self: "AccountInfo") -> int: ... @property - def code(self: "AccountInfo") -> list[int]: ... + def code(self: "AccountInfo") -> bytes: ... @property - def code_hash(self: "AccountInfo") -> list[int]: ... + def code_hash(self: "AccountInfo") -> bytes: ... def __new__( cls: Type["AccountInfo"], nonce: int = 0, - code_hash: Optional[list[int]] = None, - code: Optional[list[int]] = None, + code_hash: Optional[bytes] = None, + code: Optional[bytes] = None, ) -> "AccountInfo": ... class EvmOpts: @@ -74,26 +89,27 @@ class EVM: gas_limit: int = 2**64 - 1, tracing: bool = False, ) -> "EVM": ... - def basic(self: "EVM", address: str) -> Optional[AccountInfo]: ... + def basic(self: "EVM", address: str) -> AccountInfo: ... def insert_account_info(self: "EVM", address: str, info: AccountInfo) -> None: ... def call_raw_committing( self: "EVM", caller: str, to: str, + calldata: Optional[bytes] = None, value: Optional[int] = None, - data: Optional[list[int]] = None, - ) -> list[int]: ... + ) -> bytes: ... def call_raw( self: "EVM", caller: str, to: str, + calldata: Optional[bytes] = None, value: Optional[int] = None, - data: Optional[list[int]] = None, - ) -> list[int]: ... + commit: bool = False, + ) -> bytes: ... def deploy( self: "EVM", deployer: str, - code: list[int], + code: bytes, value: Optional[int] = None, ) -> str: ... def get_balance(self: "EVM", address: str) -> int: ... diff --git a/pytest/test.py b/pytest/test.py index 2f0290d..6d48515 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -1,5 +1,6 @@ import os.path +import pytest from pyrevm import EVM, Env, BlockEnv, AccountInfo address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # vitalik.eth @@ -24,7 +25,7 @@ def encode_uint(num: int) -> str: def encode_address(address: str) -> str: return f'{"0" * 24}{address[2:]}' - +@pytest.mark.skip("Fork not supported") def test_revm(): # set up an evm evm = EVM( @@ -64,7 +65,7 @@ def test_deploy(): # Deploy the contract deployed_at = evm.deploy( deployer=address, - code=list(bytes.fromhex("6060")), + code=bytes.fromhex("6060"), ) assert deployed_at == "0x3e4ea2156166390f880071d94458efb098473311" @@ -95,7 +96,7 @@ def test_call_raw(): result = evm.call_raw( caller=address2, to=address, - data=bytes.fromhex( + calldata=bytes.fromhex( f"aa9a0912{encode_uint(64)}{encode_uint(8)}{encode_uint(2)}" ), ) @@ -113,7 +114,7 @@ def test_call_committing(): result = evm.call_raw_committing( caller=address2, to=address, - data=bytes.fromhex( + calldata=bytes.fromhex( f"0af8b27f{encode_uint(64)}{encode_uint(8)}{encode_uint(3)}" ), ) @@ -131,7 +132,7 @@ def test_call_empty_result(): caller=address2, to=address, value=10000, - data=bytes.fromhex("d0e30db0"), + calldata=bytes.fromhex("d0e30db0"), ) assert deposit == [] @@ -139,7 +140,7 @@ def test_call_empty_result(): balance = evm.call_raw( caller=address2, to=address, - data=bytes.fromhex("70a08231" + encode_address(address2)), + calldata=bytes.fromhex("70a08231" + encode_address(address2)), ) assert int.from_bytes(balance, "big") == 10000 diff --git a/src/evm.rs b/src/evm.rs index 9024a67..00f8375 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,159 +1,147 @@ +use std::collections::btree_map::Entry; +use std::fmt::Debug; + +use foundry_evm::executors::RawCallResult; +use pyo3::exceptions::PyRuntimeError; +use pyo3::prelude::*; +use revm::{Database, DatabaseCommit, Evm, EvmBuilder, InMemoryDB, Inspector, inspector_handle_register, primitives::U256}; +use revm::db::{CacheDB, DbAccount, EmptyDB}; +use revm::inspectors::NoOpInspector; +use revm::precompile::{Address, Bytes, Log}; +use revm::primitives::{BlockEnv, Bytecode, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, ExecutionResult, HaltReason, HandlerCfg, Output, ResultAndState, SpecId, SuccessReason, TransactTo, TxEnv}; +use revm::primitives::ExecutionResult::{Halt, Revert, Success}; +use revm::precompile::B256; +use tracing::{trace, warn}; + use crate::{ types::{AccountInfo, Env}, utils::addr, }; -use foundry_evm::{ - backend::Backend, - executors::{Executor, ExecutorBuilder}, - fork::CreateFork, - opts::EvmOpts, - utils::RuntimeOrHandle, -}; -use pyo3::exceptions::PyRuntimeError; -use pyo3::prelude::*; -use revm::{primitives::U256, Database}; -use std::fmt::Debug; +#[derive(Clone, Debug)] #[pyclass] -pub struct EVM(Executor); +pub struct EVM { + /// The underlying `revm::Database` that contains the EVM storage. + // Note: We do not store an EVM here, since we are really + // only interested in the database. REVM's `EVM` is a thin + // wrapper around spawning a new EVM on every call anyway, + // so the performance difference should be negligible. + pub db: CacheDB, + /// The EVM environment. + pub env: RevmEnv, + pub handler_cfg: HandlerCfg, + /// The gas limit for calls and deployments. This is different from the gas limit imposed by + /// the passed in environment, as those limits are used by the EVM for certain opcodes like + /// `gaslimit`. + gas_limit: U256, +} impl EVM { - pub fn db(&self) -> &Backend { - &self.0.backend + pub fn db(&self) -> &CacheDB { + &self.db } } -fn pyerr(err: T) -> pyo3::PyErr { +fn pyerr(err: T) -> PyErr { PyRuntimeError::new_err(format!("{:?}", err)) } #[pymethods] impl EVM { #[new] - #[pyo3(signature = (env=None, fork_url=None, fork_block_number=None, gas_limit=18446744073709551615, tracing=false))] + #[pyo3(signature = (env=None, gas_limit=18446744073709551615, tracing=false))] fn new( env: Option, - fork_url: Option, - fork_block_number: Option, gas_limit: u64, - tracing: bool, + tracing: bool ) -> PyResult { - let evm_opts = EvmOpts { - fork_url: fork_url.clone(), - fork_block_number, - ..Default::default() - }; - - let fork_opts = if let Some(fork_url) = fork_url { - let env = RuntimeOrHandle::new() - .block_on(evm_opts.evm_env()) - .map_err(pyerr)?; - Some(CreateFork { - url: fork_url, - enable_caching: true, - env, - evm_opts, - }) - } else { - None - }; - - let db = Backend::spawn(fork_opts); - - let executor = ExecutorBuilder::default() - .gas_limit(U256::from(gas_limit)) - .inspectors(|stack| stack.trace(tracing)) - .build(env.unwrap_or_default().into(), db); - - Ok(EVM(executor)) + // let db = CacheDB::new(EmptyDB::default()); + let db = CacheDB::new(Default::default()); + Ok(EVM { + // db: CacheDB::new(InMemoryDB::new(EmptyDB::new())), + db, + env: env.or(Some(Env::default())).unwrap().into(), + gas_limit: U256::from(gas_limit), + handler_cfg: HandlerCfg::new(SpecId::LATEST), + }) + } + + /// Get basic account information. + fn basic(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult { + let acc = _self.db.basic(addr(address)?).map_err(pyerr)?; + Ok(acc.map(Into::into).unwrap_or_else(AccountInfo::default)) } - /// Inserts the provided account information in the database at - /// the specified address. - fn basic(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult> { - let db = &mut _self.0.backend; - let acc = db.basic(addr(address)?).map_err(pyerr)?; - Ok(acc.map(Into::into)) + /// Get account code by its hash. + #[pyo3(signature = (code_hash))] + fn code_by_hash(&mut self, code_hash: &str) -> PyResult> { + let hash = code_hash.parse::().map_err(pyerr)?; + Ok(self.db.code_by_hash(hash).map(|c| c.bytecode.to_vec()).map_err(pyerr)?) } - /// Inserts the provided account information in the database at - /// the specified address. + /// Get storage value of address at index. + fn storage(&mut self, address: &str, index: U256) -> PyResult { + Ok(self.db.storage(addr(address)?, index).map_err(pyerr)?) + } + + /// Get block hash by block number. + fn block_hash(&mut self, number: U256) -> PyResult> { + Ok(self.db.block_hash(number).map(|h| h.to_vec()).map_err(pyerr)?) + } + + /// Inserts the provided account information in the database at the specified address. fn insert_account_info( mut _self: PyRefMut<'_, Self>, address: &str, info: AccountInfo, ) -> PyResult<()> { - let db = &mut _self.0.backend; - db.insert_account_info(addr(address)?, info.into()); - + _self.db.insert_account_info(addr(address)?, info.into()); Ok(()) } /// Set the balance of a given address. fn set_balance(mut _self: PyRefMut<'_, Self>, address: &str, balance: U256) -> PyResult<()> { - _self - .0 - .set_balance(addr(address)?, balance) - .map_err(pyerr)?; + let target = addr(address)?; + let mut info = _self.db.basic(target).map_err(pyerr)?.unwrap_or_default(); + info.balance = balance; + _self.db.insert_account_info(target, info.clone()); + if !_self.db.accounts.contains_key(&target) { + panic!("Account not found after insert"); + } + // assert_eq!(_self.db.accounts.entry(target).map(|o| o.map(|b| b.info)), Some(info)); + // assert_eq!(_self.db.basic(target).map_err(pyerr)?, Entry::Occupied(info)); Ok(()) } /// Retrieve the balance of a given address. - fn get_balance(_self: PyRef<'_, Self>, address: &str) -> PyResult { - let balance = _self.0.get_balance(addr(address)?).map_err(pyerr)?; - Ok(balance) + fn get_balance(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult> { + // Ok(_self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) + let acc = _self.db.basic(addr(address)?).map_err(pyerr)?; + Ok(acc.map(|a| a.balance)) } - fn call_raw_committing( + // runs a raw call and returns the result + #[pyo3(signature = (caller, to, calldata=None, value=None))] + pub fn call_raw_committing( mut _self: PyRefMut<'_, Self>, caller: &str, to: &str, + calldata: Option>, value: Option, - data: Option>, ) -> PyResult> { - let res = _self - .0 - .call_raw_committing( - // TODO: The constant type conversions when - // crossing the boundary is annoying. Can we pass it - // a type that's already an `Address`? - addr(caller)?, - addr(to)?, - data.unwrap_or_default().into(), - value.unwrap_or_default(), - ) - .map_err(pyerr)?; - - if res.reverted { - return Err(pyerr(res.exit_reason)); - } - - // TODO: Return the traces back to the user. - Ok(res.result.to_vec()) + call_raw(_self, caller, to, calldata, value, true) } - fn call_raw( - _self: PyRef<'_, Self>, + #[pyo3(signature = (caller, to, calldata=None, value=None, commit=false))] + pub fn call_raw( + mut _self: PyRefMut<'_, Self>, caller: &str, to: &str, + calldata: Option>, value: Option, - data: Option>, + commit: bool, ) -> PyResult> { - let res = _self - .0 - .call_raw( - addr(caller)?, - addr(to)?, - data.unwrap_or_default().into(), - value.unwrap_or_default(), - ) - .map_err(pyerr)?; - - if res.reverted { - return Err(pyerr(res.exit_reason)); - } - - Ok(res.result.to_vec()) + call_raw(_self, caller, to, calldata, value, commit) } /// Deploy a contract with the given code. @@ -164,16 +152,129 @@ impl EVM { value: Option, _abi: Option<&str>, ) -> PyResult { - let res = _self - .0 - .deploy( - addr(deployer)?, - code.unwrap_or_default().into(), - value.unwrap_or_default(), - None, - ) + let env = build_test_env(&_self, addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); + let address = deploy_with_env(_self, env) .map_err(pyerr)?; + Ok(format!("{:?}", address)) + } + +} + +/// Creates the environment to use when executing a transaction in a test context +/// +/// If using a backend with cheatcodes, `tx.gas_price` and `block.number` will be overwritten by +/// the cheatcode state inbetween calls. +fn build_test_env( + evm: &EVM, + caller: Address, + transact_to: TransactTo, + data: Bytes, + value: U256, +) -> EnvWithHandlerCfg { + let env = revm::primitives::Env { + cfg: evm.env.cfg.clone(), + // We always set the gas price to 0, so we can execute the transaction regardless of + // network conditions - the actual gas price is kept in `evm.block` and is applied by + // the cheatcode handler if it is enabled + block: BlockEnv { + basefee: U256::ZERO, + gas_limit: evm.gas_limit, + ..evm.env.block.clone() + }, + tx: TxEnv { + caller, + transact_to, + data, + value, + // As above, we set the gas price to 0. + gas_price: U256::ZERO, + gas_priority_fee: None, + gas_limit: evm.gas_limit.to(), + ..evm.env.tx.clone() + }, + }; + + EnvWithHandlerCfg::new_with_spec_id(Box::new(env), evm.handler_cfg.spec_id) +} - Ok(format!("{:?}", res.address)) +/// Deploys a contract using the given `env` and commits the new state to the underlying +/// database +fn deploy_with_env( + mut _self: PyRefMut<'_, EVM>, + env: EnvWithHandlerCfg, +) -> PyResult
{ + debug_assert!( + matches!(env.tx.transact_to, TransactTo::Create(_)), + "Expect create transaction" + ); + trace!(sender=?env.tx.caller, "deploying contract"); + + let ResultAndState { + result, state + } = Evm::builder() + .with_ref_db(&_self.db) + .with_env_with_handler_cfg(env) + .build() + .transact() + .map_err(pyerr)?; + + match &result { + Success { reason, gas_used, gas_refunded, logs, output } => { + warn!(reason=?reason, gas_used, gas_refunded, "contract deployed"); + match output { + Output::Create(_, address) => { + _self.db.commit(state); + Ok(address.unwrap()) + } + _ => Err(pyerr("Invalid output")), + } + }, + _ => Err(pyerr(result.clone())), } } + + +fn call_raw_with_env( + mut _self: PyRefMut<'_, EVM>, + env: EnvWithHandlerCfg, +) -> PyResult { + debug_assert!( + matches!(env.tx.transact_to, TransactTo::Call(_)), + "Expect call transaction" + ); + trace!(sender=?env.tx.caller, "deploying contract"); + + let transaction = Evm::builder() + .with_env_with_handler_cfg(env) + .build() + .transact() + .map_err(pyerr)?; + + let ResultAndState { + result, state + } = transaction; + + match &result { + Success { reason, gas_used, gas_refunded, logs, output } => { + let data = output.clone().into_data(); + trace!(reason=?reason, gas_used, gas_refunded, "call done"); + Ok(data) + }, + _ => Err(pyerr(result.clone())), + } +} + +fn call_raw( + mut _self: PyRefMut<'_, EVM>, + caller: &str, + to: &str, + calldata: Option>, + value: Option, + commit: bool, +) -> PyResult> { + let env = build_test_env(&_self, addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); + let mut result = call_raw_with_env(_self, env).map_err(pyerr)?; + // self.commit(&mut result); + // TODO: Return the traces back to the user. + Ok(result.to_vec()) +} diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 94a6476..4ba4a71 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -115,6 +115,36 @@ impl BlockEnv { })) } + #[getter] + fn number(&self) -> U256 { + self.0.number + } + + #[getter] + fn coinbase(&self) -> String { + self.0.coinbase.to_string() + } + + #[getter] + fn timestamp(&self) -> U256 { + self.0.timestamp + } + + #[getter] + fn difficulty(&self) -> U256 { + self.0.difficulty + } + + #[getter] + fn prevrandao(&self) -> Option<[u8; 32]> { + self.0.prevrandao.map(|i| i.0) + } + + #[getter] + fn basefee(&self) -> U256 { + self.0.basefee + } + fn __str__(&self) -> PyResult { Ok(format!("{:?}", self)) } From 887774689e0145bf19fbb95504a838fd0196a8b8 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Sat, 16 Mar 2024 10:05:19 +0100 Subject: [PATCH 02/33] Use `load_account` instead of `basic` --- pytest/test.py | 6 +++--- src/evm.rs | 36 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pytest/test.py b/pytest/test.py index 6d48515..b9f168d 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -88,9 +88,9 @@ def test_balances(): def test_call_raw(): evm = EVM() - evm.insert_account_info( - address, AccountInfo(code=load_contract_bin("full_math.bin")) - ) + info = AccountInfo(code=load_contract_bin("full_math.bin")) + evm.insert_account_info(address, info) + assert evm.basic(address).code == info.code # mulDiv() -> 64 * 8 / 2 result = evm.call_raw( diff --git a/src/evm.rs b/src/evm.rs index 00f8375..dd3c0d5 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -57,8 +57,8 @@ impl EVM { ) -> PyResult { // let db = CacheDB::new(EmptyDB::default()); let db = CacheDB::new(Default::default()); + // let db = CacheDB::new(InMemoryDB::new(EmptyDB::new())); Ok(EVM { - // db: CacheDB::new(InMemoryDB::new(EmptyDB::new())), db, env: env.or(Some(Env::default())).unwrap().into(), gas_limit: U256::from(gas_limit), @@ -68,8 +68,8 @@ impl EVM { /// Get basic account information. fn basic(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult { - let acc = _self.db.basic(addr(address)?).map_err(pyerr)?; - Ok(acc.map(Into::into).unwrap_or_else(AccountInfo::default)) + let db_account = _self.db.load_account(addr(address)?).map_err(pyerr)?; + Ok(db_account.info.clone().into()) } /// Get account code by its hash. @@ -105,25 +105,21 @@ impl EVM { let mut info = _self.db.basic(target).map_err(pyerr)?.unwrap_or_default(); info.balance = balance; _self.db.insert_account_info(target, info.clone()); - if !_self.db.accounts.contains_key(&target) { - panic!("Account not found after insert"); - } - // assert_eq!(_self.db.accounts.entry(target).map(|o| o.map(|b| b.info)), Some(info)); - // assert_eq!(_self.db.basic(target).map_err(pyerr)?, Entry::Occupied(info)); + assert_eq!(_self.db.load_account(target).map(|a| a.info.clone()).map_err(pyerr)?, info); Ok(()) } /// Retrieve the balance of a given address. - fn get_balance(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult> { + fn get_balance(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult { // Ok(_self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) - let acc = _self.db.basic(addr(address)?).map_err(pyerr)?; - Ok(acc.map(|a| a.balance)) + let acc = _self.db.load_account(addr(address)?).map_err(pyerr)?; + Ok(acc.info.balance) } // runs a raw call and returns the result #[pyo3(signature = (caller, to, calldata=None, value=None))] pub fn call_raw_committing( - mut _self: PyRefMut<'_, Self>, + mut _self: &mut PyRefMut<'_, Self>, caller: &str, to: &str, calldata: Option>, @@ -153,7 +149,7 @@ impl EVM { _abi: Option<&str>, ) -> PyResult { let env = build_test_env(&_self, addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); - let address = deploy_with_env(_self, env) + let address = deploy_with_env(&_self, env) .map_err(pyerr)?; Ok(format!("{:?}", address)) } @@ -200,7 +196,7 @@ fn build_test_env( /// Deploys a contract using the given `env` and commits the new state to the underlying /// database fn deploy_with_env( - mut _self: PyRefMut<'_, EVM>, + mut _self: &PyRefMut<'_, EVM>, env: EnvWithHandlerCfg, ) -> PyResult
{ debug_assert!( @@ -235,8 +231,9 @@ fn deploy_with_env( fn call_raw_with_env( - mut _self: PyRefMut<'_, EVM>, + &mut _self: &mut PyRefMut<'_, EVM>, env: EnvWithHandlerCfg, + commit: bool, ) -> PyResult { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), @@ -258,6 +255,9 @@ fn call_raw_with_env( Success { reason, gas_used, gas_refunded, logs, output } => { let data = output.clone().into_data(); trace!(reason=?reason, gas_used, gas_refunded, "call done"); + if commit { + (*_self).db.commit(state); + } Ok(data) }, _ => Err(pyerr(result.clone())), @@ -265,7 +265,7 @@ fn call_raw_with_env( } fn call_raw( - mut _self: PyRefMut<'_, EVM>, + &mut _self: &mut PyRefMut<'_, EVM>, caller: &str, to: &str, calldata: Option>, @@ -273,8 +273,8 @@ fn call_raw( commit: bool, ) -> PyResult> { let env = build_test_env(&_self, addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - let mut result = call_raw_with_env(_self, env).map_err(pyerr)?; - // self.commit(&mut result); + let result = call_raw_with_env(_self, env, commit).map_err(pyerr)?; + // TODO: Return the traces back to the user. Ok(result.to_vec()) } From 02e6f49faee5c467fc480fbd806a81190137a225 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Sat, 16 Mar 2024 12:04:07 +0100 Subject: [PATCH 03/33] Allow retrieving a dict of account info --- pyrevm.pyi | 59 +++++++++++++++++++--- pytest/test.py | 38 ++++++++------- src/evm.rs | 130 ++++++++++++++++++++++++++++--------------------- 3 files changed, 147 insertions(+), 80 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index b80bad9..0208720 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -84,28 +84,71 @@ class EVM: def __new__( cls: Type["EVM"], env: Optional[Env] = None, - fork_url: Optional[str] = None, - fork_block_number: Optional[int] = None, + # fork_url: Optional[str] = None, + # fork_block_number: Optional[int] = None, gas_limit: int = 2**64 - 1, tracing: bool = False, - ) -> "EVM": ... - def basic(self: "EVM", address: str) -> AccountInfo: ... - def insert_account_info(self: "EVM", address: str, info: AccountInfo) -> None: ... + spec_id="latest", + ) -> "EVM": + """ + Creates a new EVM instance. + :param env: The environment. + :param gas_limit: The gas limit. + :param tracing: Whether to enable tracing. + :param spec_id: The spec ID. + """ + + def get_accounts(self) -> dict[str, AccountInfo]: + """ + :return: a dictionary of account addresses to account info + """ + + def basic(self: "EVM", address: str) -> AccountInfo: + """ + Returns the basic account info for the given address. + :param address: The address of the account. + :return: The account info. + """ + + def insert_account_info(self: "EVM", address: str, info: AccountInfo) -> None: + """ + Inserts the given account info into the state. + :param address: The address of the account. + :param info: The account info. + """ + def call_raw_committing( self: "EVM", caller: str, to: str, calldata: Optional[bytes] = None, value: Optional[int] = None, - ) -> bytes: ... + ) -> bytes: + """ + Processes a raw call, committing the result to the state. + :param caller: The address of the caller. + :param to: The address of the callee. + :param calldata: The calldata. + :param value: The value. + :return: The return data. + """ + def call_raw( self: "EVM", caller: str, to: str, calldata: Optional[bytes] = None, value: Optional[int] = None, - commit: bool = False, - ) -> bytes: ... + ) -> bytes: + """ + Processes a raw call, without committing the result to the state. + :param caller: The address of the caller. + :param to: The address of the callee. + :param calldata: The calldata. + :param value: The value. + :return: The return data. + """ + def deploy( self: "EVM", deployer: str, diff --git a/pytest/test.py b/pytest/test.py index b9f168d..efe13c4 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -4,7 +4,7 @@ from pyrevm import EVM, Env, BlockEnv, AccountInfo address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # vitalik.eth -address2 = "0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +address2 = "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" fork_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27" @@ -128,19 +128,23 @@ def test_call_empty_result(): evm.set_balance(address2, 10000) - deposit = evm.call_raw_committing( - caller=address2, - to=address, - value=10000, - calldata=bytes.fromhex("d0e30db0"), - ) - - assert deposit == [] - - balance = evm.call_raw( - caller=address2, - to=address, - calldata=bytes.fromhex("70a08231" + encode_address(address2)), - ) - - assert int.from_bytes(balance, "big") == 10000 + try: + deposit = evm.call_raw_committing( + caller=address2, + to=address, + value=10000, + calldata=bytes.fromhex("d0e30db0"), + ) + + assert deposit == [] + + balance = evm.call_raw( + caller=address2, + to=address, + calldata=bytes.fromhex("70a08231" + encode_address(address2)), + ) + + assert int.from_bytes(balance, "big") == 10000 + except Exception as e: + accs = {k: (v.balance, any(v.code)) for k, v in evm.get_accounts().items()} + raise Exception(f"{e} - {accs}") from e diff --git a/src/evm.rs b/src/evm.rs index dd3c0d5..02dc4dc 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,16 +1,15 @@ -use std::collections::btree_map::Entry; +use std::collections::HashMap; use std::fmt::Debug; +use std::hash::Hash; -use foundry_evm::executors::RawCallResult; use pyo3::exceptions::PyRuntimeError; use pyo3::prelude::*; -use revm::{Database, DatabaseCommit, Evm, EvmBuilder, InMemoryDB, Inspector, inspector_handle_register, primitives::U256}; -use revm::db::{CacheDB, DbAccount, EmptyDB}; -use revm::inspectors::NoOpInspector; -use revm::precompile::{Address, Bytes, Log}; -use revm::primitives::{BlockEnv, Bytecode, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, ExecutionResult, HaltReason, HandlerCfg, Output, ResultAndState, SpecId, SuccessReason, TransactTo, TxEnv}; -use revm::primitives::ExecutionResult::{Halt, Revert, Success}; +use revm::{Database, DatabaseCommit, Evm, InMemoryDB, primitives::U256}; +use revm::db::{CacheDB}; +use revm::precompile::{Address, Bytes}; use revm::precompile::B256; +use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::ExecutionResult::{Success}; use tracing::{trace, warn}; use crate::{ @@ -18,6 +17,8 @@ use crate::{ utils::addr, }; +type DB = CacheDB; + #[derive(Clone, Debug)] #[pyclass] pub struct EVM { @@ -26,7 +27,7 @@ pub struct EVM { // only interested in the database. REVM's `EVM` is a thin // wrapper around spawning a new EVM on every call anyway, // so the performance difference should be negligible. - pub db: CacheDB, + pub db: DB, /// The EVM environment. pub env: RevmEnv, pub handler_cfg: HandlerCfg, @@ -37,7 +38,7 @@ pub struct EVM { } impl EVM { - pub fn db(&self) -> &CacheDB { + pub fn db(&self) -> &DB { &self.db } } @@ -49,11 +50,12 @@ fn pyerr(err: T) -> PyErr { #[pymethods] impl EVM { #[new] - #[pyo3(signature = (env=None, gas_limit=18446744073709551615, tracing=false))] + #[pyo3(signature = (env=None, gas_limit=18446744073709551615, tracing=false, spec_id="LATEST"))] fn new( env: Option, gas_limit: u64, - tracing: bool + tracing: bool, + spec_id: &str, ) -> PyResult { // let db = CacheDB::new(EmptyDB::default()); let db = CacheDB::new(Default::default()); @@ -62,16 +64,25 @@ impl EVM { db, env: env.or(Some(Env::default())).unwrap().into(), gas_limit: U256::from(gas_limit), - handler_cfg: HandlerCfg::new(SpecId::LATEST), + handler_cfg: HandlerCfg::new(SpecId::from(spec_id)), }) } /// Get basic account information. - fn basic(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult { - let db_account = _self.db.load_account(addr(address)?).map_err(pyerr)?; + fn basic(&mut self, address: &str) -> PyResult { + let db_account = self.db.load_account(addr(address)?).map_err(pyerr)?; Ok(db_account.info.clone().into()) } + fn get_accounts(&self) -> PyResult> {context + self.db + .journaled_state + .load_account(tx_caller, &mut context.evm.inner.db)?; + Ok(self.db.accounts.iter().map( + |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) + ).collect()) + } + /// Get account code by its hash. #[pyo3(signature = (code_hash))] fn code_by_hash(&mut self, code_hash: &str) -> PyResult> { @@ -91,67 +102,83 @@ impl EVM { /// Inserts the provided account information in the database at the specified address. fn insert_account_info( - mut _self: PyRefMut<'_, Self>, + &mut self, address: &str, info: AccountInfo, ) -> PyResult<()> { - _self.db.insert_account_info(addr(address)?, info.into()); + self.db.insert_account_info(addr(address)?, info.into()); Ok(()) } /// Set the balance of a given address. - fn set_balance(mut _self: PyRefMut<'_, Self>, address: &str, balance: U256) -> PyResult<()> { + fn set_balance(&mut self, address: &str, balance: U256) -> PyResult<()> { let target = addr(address)?; - let mut info = _self.db.basic(target).map_err(pyerr)?.unwrap_or_default(); + let mut info = self.db.basic(target).map_err(pyerr)?.unwrap_or_default(); info.balance = balance; - _self.db.insert_account_info(target, info.clone()); - assert_eq!(_self.db.load_account(target).map(|a| a.info.clone()).map_err(pyerr)?, info); + self.db.insert_account_info(target, info.clone()); + assert_eq!(self.db.load_account(target).map(|a| a.info.clone()).map_err(pyerr)?, info); Ok(()) } /// Retrieve the balance of a given address. - fn get_balance(mut _self: PyRefMut<'_, Self>, address: &str) -> PyResult { - // Ok(_self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) - let acc = _self.db.load_account(addr(address)?).map_err(pyerr)?; + fn get_balance(&mut self, address: &str) -> PyResult { + // Ok(self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) + let acc = self.db.load_account(addr(address)?).map_err(pyerr)?; Ok(acc.info.balance) } // runs a raw call and returns the result #[pyo3(signature = (caller, to, calldata=None, value=None))] pub fn call_raw_committing( - mut _self: &mut PyRefMut<'_, Self>, + &mut self, caller: &str, to: &str, calldata: Option>, value: Option, ) -> PyResult> { - call_raw(_self, caller, to, calldata, value, true) + match call_raw(self, caller, to, calldata, value) + { + Ok((data, state)) => { + self.db.commit(state); + Ok(data.to_vec()) + }, + Err(e) => Err(e), + } } - #[pyo3(signature = (caller, to, calldata=None, value=None, commit=false))] + #[pyo3(signature = (caller, to, calldata=None, value=None))] pub fn call_raw( - mut _self: PyRefMut<'_, Self>, + &self, caller: &str, to: &str, calldata: Option>, value: Option, - commit: bool, ) -> PyResult> { - call_raw(_self, caller, to, calldata, value, commit) + match call_raw(self, caller, to, calldata, value) + { + // todo: return state to the caller + Ok((data, state)) => Ok(data.to_vec()), + Err(e) => Err(e), + } } /// Deploy a contract with the given code. fn deploy( - mut _self: PyRefMut<'_, Self>, + &mut self, deployer: &str, code: Option>, value: Option, _abi: Option<&str>, ) -> PyResult { - let env = build_test_env(&_self, addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); - let address = deploy_with_env(&_self, env) - .map_err(pyerr)?; - Ok(format!("{:?}", address)) + let env = build_test_env(self, addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); + match deploy_with_env(&self.db, env) + { + Ok((address, state)) => { + self.db.commit(state); + Ok(format!("{:?}", address)) + }, + Err(e) => Err(e), + } } } @@ -196,9 +223,9 @@ fn build_test_env( /// Deploys a contract using the given `env` and commits the new state to the underlying /// database fn deploy_with_env( - mut _self: &PyRefMut<'_, EVM>, + db: &DB, env: EnvWithHandlerCfg, -) -> PyResult
{ +) -> PyResult<(Address, State)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Create(_)), "Expect create transaction" @@ -208,7 +235,7 @@ fn deploy_with_env( let ResultAndState { result, state } = Evm::builder() - .with_ref_db(&_self.db) + .with_ref_db(&db) .with_env_with_handler_cfg(env) .build() .transact() @@ -219,8 +246,7 @@ fn deploy_with_env( warn!(reason=?reason, gas_used, gas_refunded, "contract deployed"); match output { Output::Create(_, address) => { - _self.db.commit(state); - Ok(address.unwrap()) + Ok((address.unwrap(), state)) } _ => Err(pyerr("Invalid output")), } @@ -231,10 +257,9 @@ fn deploy_with_env( fn call_raw_with_env( - &mut _self: &mut PyRefMut<'_, EVM>, + db: &DB, env: EnvWithHandlerCfg, - commit: bool, -) -> PyResult { +) -> PyResult<(Bytes, State)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), "Expect call transaction" @@ -242,6 +267,7 @@ fn call_raw_with_env( trace!(sender=?env.tx.caller, "deploying contract"); let transaction = Evm::builder() + .with_ref_db(&db) .with_env_with_handler_cfg(env) .build() .transact() @@ -255,26 +281,20 @@ fn call_raw_with_env( Success { reason, gas_used, gas_refunded, logs, output } => { let data = output.clone().into_data(); trace!(reason=?reason, gas_used, gas_refunded, "call done"); - if commit { - (*_self).db.commit(state); - } - Ok(data) + Ok((data, state)) }, + // todo: state might have changed even if the call failed _ => Err(pyerr(result.clone())), } } fn call_raw( - &mut _self: &mut PyRefMut<'_, EVM>, + evm: &EVM, caller: &str, to: &str, calldata: Option>, value: Option, - commit: bool, -) -> PyResult> { - let env = build_test_env(&_self, addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - let result = call_raw_with_env(_self, env, commit).map_err(pyerr)?; - - // TODO: Return the traces back to the user. - Ok(result.to_vec()) +) -> PyResult<(Bytes, State)> { + let env = build_test_env(&evm, addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); + call_raw_with_env(&evm.db, env) } From 33b94e55e4b207deb1aaa7e9397b5bb86adad2b2 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Mon, 18 Mar 2024 12:14:19 +0100 Subject: [PATCH 04/33] Copy EmptyDBWrapper from Foundry --- Cargo.lock | 5809 ++++++--------------------------------- Cargo.toml | 5 +- pytest/test.py | 12 +- src/empty_db_wrapper.rs | 35 + src/evm.rs | 42 +- src/lib.rs | 1 + 6 files changed, 843 insertions(+), 5061 deletions(-) create mode 100644 src/empty_db_wrapper.rs diff --git a/Cargo.lock b/Cargo.lock index a7471ca..8088c71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,42 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" version = "0.8.11" @@ -50,109 +14,12 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - [[package]] name = "allocator-api2" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" -[[package]] -name = "alloy-chains" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96c81b05c893348760f232c4cc6a6a77fd91cfb09885d4eaad25cd03bd7732e" -dependencies = [ - "num_enum", - "serde", - "strum 0.26.1", -] - -[[package]] -name = "alloy-dyn-abi" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2919acdad13336bc5dc26b636cdd6892c2f27fb0d4a58320a00c2713cf6a4e9a" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "arbitrary", - "const-hex", - "derive_arbitrary", - "derive_more", - "itoa", - "proptest", - "serde", - "serde_json", - "winnow 0.6.5", -] - -[[package]] -name = "alloy-eips" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-genesis" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types", - "serde", -] - -[[package]] -name = "alloy-json-abi" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ed0f2a6c3a1c947b4508522a53a190dba8f94dcd4e3e1a5af945a498e78f2f" -dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-json-rpc" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-network" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-eips", - "alloy-json-rpc", - "alloy-primitives", - "alloy-rlp", - "serde", -] - [[package]] name = "alloy-primitives" version = "0.6.4" @@ -160,318 +27,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", - "arbitrary", "bytes", "cfg-if", "const-hex", - "derive_arbitrary", "derive_more", - "ethereum_ssz", - "getrandom", "hex-literal", "itoa", "k256", "keccak-asm", "proptest", - "proptest-derive", "rand", "ruint", "serde", "tiny-keccak", ] -[[package]] -name = "alloy-providers" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-network", - "alloy-primitives", - "alloy-rpc-client", - "alloy-rpc-trace-types", - "alloy-rpc-types", - "alloy-transport", - "alloy-transport-http", - "async-trait", - "auto_impl", - "reqwest", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-pubsub" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", - "bimap", - "futures", - "serde", - "serde_json", - "tokio", - "tower", - "tracing", -] - [[package]] name = "alloy-rlp" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ - "alloy-rlp-derive", "arrayvec", "bytes", ] -[[package]] -name = "alloy-rlp-derive" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "alloy-rpc-client" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "alloy-transport-http", - "futures", - "pin-project", - "reqwest", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-rpc-trace-types" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "itertools 0.12.1", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-signer" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-network", - "alloy-primitives", - "async-trait", - "auto_impl", - "coins-bip32", - "coins-bip39", - "elliptic-curve", - "eth-keystore", - "k256", - "rand", - "thiserror", -] - -[[package]] -name = "alloy-sol-macro" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" -dependencies = [ - "alloy-json-abi", - "const-hex", - "dunce", - "heck", - "indexmap", - "proc-macro-error", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.52", - "syn-solidity", - "tiny-keccak", -] - -[[package]] -name = "alloy-sol-type-parser" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0045cc89524e1451ccf33e8581355b6027ac7c6e494bb02959d4213ad0d8e91d" -dependencies = [ - "winnow 0.6.5", -] - -[[package]] -name = "alloy-sol-types" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "const-hex", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-json-rpc", - "base64 0.21.7", - "futures-util", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "url", - "wasm-bindgen-futures", -] - -[[package]] -name = "alloy-transport-http" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "reqwest", - "serde_json", - "tower", - "url", -] - -[[package]] -name = "alloy-transport-ipc" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-json-rpc", - "alloy-pubsub", - "alloy-transport", - "bytes", - "futures", - "interprocess", - "pin-project", - "serde_json", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "alloy-transport-ws" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=785c667#785c667813a6c76794044b943df58fc6e397734d" -dependencies = [ - "alloy-pubsub", - "alloy-transport", - "futures", - "http", - "serde_json", - "tokio", - "tokio-tungstenite", - "tracing", - "ws_stream_wasm", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" - -[[package]] -name = "anstyle-parse" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "arbitrary" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" - [[package]] name = "ark-ff" version = "0.3.0" @@ -502,7 +82,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "digest 0.10.7", - "itertools 0.10.5", + "itertools", "num-bigint", "num-traits", "paste", @@ -603,96 +183,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] -name = "ascii-canvas" -version = "3.0.0" +name = "aurora-engine-modexp" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +checksum = "bfacad86e9e138fca0670949eb8ed4ffdf73a55bded8887efe0863cd1a3a6f70" dependencies = [ - "term", + "hex", + "num", ] [[package]] -name = "async-channel" -version = "2.2.0" +name = "auto_impl" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" -dependencies = [ - "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.0", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-lock" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" -dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", - "pin-project-lite", -] - -[[package]] -name = "async-task" -version = "4.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" - -[[package]] -name = "async-trait" -version = "0.1.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - -[[package]] -name = "atomic" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "aurora-engine-modexp" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfacad86e9e138fca0670949eb8ed4ffdf73a55bded8887efe0863cd1a3a6f70" -dependencies = [ - "hex", - "num", -] - -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -705,57 +209,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64ct" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - -[[package]] -name = "bimap" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" - [[package]] name = "bit-set" version = "0.5.3" @@ -782,10 +247,6 @@ name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" -dependencies = [ - "arbitrary", - "serde", -] [[package]] name = "bitvec" @@ -795,20 +256,10 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", - "serde", "tap", "wyz", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -818,22 +269,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "fastrand", - "futures-io", - "futures-lite", - "piper", - "tracing", -] - [[package]] name = "blst" version = "0.3.11" @@ -846,50 +281,12 @@ dependencies = [ "zeroize", ] -[[package]] -name = "bs58" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" -dependencies = [ - "sha2 0.10.8", - "tinyvec", -] - -[[package]] -name = "bstr" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "build_const" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" - -[[package]] -name = "bumpalo" -version = "3.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" - [[package]] name = "byte-slice-cast" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" -[[package]] -name = "bytemuck" -version = "1.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" - [[package]] name = "byteorder" version = "1.5.0" @@ -901,30 +298,6 @@ name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" -dependencies = [ - "serde", -] - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] [[package]] name = "c-kzg" @@ -941,4912 +314,1385 @@ dependencies = [ ] [[package]] -name = "camino" -version = "1.1.6" +name = "cc" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] -name = "cargo-platform" -version = "0.1.7" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" -dependencies = [ - "serde", -] +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cargo_metadata" -version = "0.18.1" +name = "const-hex" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +checksum = "efbd12d49ab0eaf8193ba9175e45f56bbc2e4b27d57b8cfe62aa47942a46b9a9" dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.22", + "cfg-if", + "cpufeatures", + "hex", + "proptest", "serde", - "serde_json", - "thiserror", ] [[package]] -name = "cc" -version = "1.0.90" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" -dependencies = [ - "jobserver", - "libc", -] +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "chrono" -version = "0.4.35" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "windows-targets 0.52.4", + "libc", ] [[package]] -name = "cipher" -version = "0.4.4" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] -name = "clap" -version = "4.5.2" +name = "crypto-bigint" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "clap_builder", - "clap_derive", + "generic-array", + "rand_core", + "subtle", + "zeroize", ] [[package]] -name = "clap_builder" -version = "4.5.2" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim 0.11.0", - "terminal_size", - "unicase", - "unicode-width", + "generic-array", + "typenum", ] [[package]] -name = "clap_derive" -version = "4.5.0" +name = "der" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.52", + "const-oid", + "zeroize", ] [[package]] -name = "clap_lex" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" - -[[package]] -name = "coins-bip32" -version = "0.8.7" +name = "derivative" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "bs58", - "coins-core", - "digest 0.10.7", - "hmac 0.12.1", - "k256", - "serde", - "sha2 0.10.8", - "thiserror", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "coins-bip39" -version = "0.8.7" +name = "derive_more" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "bitvec", - "coins-bip32", - "hmac 0.12.1", - "once_cell", - "pbkdf2 0.12.2", - "rand", - "sha2 0.10.8", - "thiserror", + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", ] [[package]] -name = "coins-core" -version = "0.8.7" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "base64 0.21.7", - "bech32", - "bs58", - "digest 0.10.7", "generic-array", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2 0.10.8", - "sha3", - "thiserror", ] [[package]] -name = "coins-ledger" -version = "0.10.1" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e076e6e5d9708f0b90afe2dbe5a8ba406b5c794347661e6e44618388c7e3a31" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "async-trait", - "byteorder", - "cfg-if", - "getrandom", - "hex", - "hidapi-rusb", - "js-sys", - "log", - "nix", - "once_cell", - "thiserror", - "tokio", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", + "block-buffer", + "const-oid", + "crypto-common", + "subtle", ] [[package]] -name = "colorchoice" -version = "1.0.0" +name = "dyn-clone" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] -name = "comfy-table" -version = "7.1.0" +name = "ecdsa" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "crossterm", - "strum 0.25.0", - "strum_macros 0.25.3", - "unicode-width", + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", ] [[package]] -name = "concurrent-queue" -version = "2.4.0" +name = "either" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" -dependencies = [ - "crossbeam-utils", -] +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] -name = "const-hex" -version = "1.11.1" +name = "elliptic-curve" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbd12d49ab0eaf8193ba9175e45f56bbc2e4b27d57b8cfe62aa47942a46b9a9" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", ] [[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "enumn" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] [[package]] -name = "convert_case" -version = "0.4.0" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "core-foundation" -version = "0.9.4" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "core-foundation-sys", "libc", + "windows-sys", ] [[package]] -name = "core-foundation-sys" -version = "0.8.6" +name = "fastrand" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] -name = "cpufeatures" -version = "0.2.12" +name = "fastrlp" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "libc", + "arrayvec", + "auto_impl", + "bytes", ] [[package]] -name = "crc32fast" -version = "1.4.0" +name = "ff" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "cfg-if", + "rand_core", + "subtle", ] [[package]] -name = "crossbeam-deque" -version = "0.8.5" +name = "fixed-hash" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", + "byteorder", + "rand", + "rustc-hex", + "static_assertions", ] [[package]] -name = "crossbeam-epoch" -version = "0.9.18" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "crossbeam-utils" -version = "0.8.19" +name = "funty" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] -name = "crossterm" -version = "0.27.0" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "bitflags 2.4.2", - "crossterm_winapi", - "libc", - "parking_lot", - "winapi", + "typenum", + "version_check", + "zeroize", ] [[package]] -name = "crossterm_winapi" -version = "0.9.1" +name = "getrandom" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ - "winapi", + "cfg-if", + "libc", + "wasi", ] [[package]] -name = "crunchy" -version = "0.2.2" +name = "glob" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] -name = "crypto-bigint" -version = "0.5.5" +name = "group" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "generic-array", + "ff", "rand_core", "subtle", - "zeroize", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "hashbrown" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "generic-array", - "typenum", + "ahash", + "allocator-api2", ] [[package]] -name = "crypto-mac" -version = "0.11.1" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "ctr" -version = "0.9.2" +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "cipher", + "digest 0.10.7", ] [[package]] -name = "darling" -version = "0.20.8" +name = "impl-codec" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ - "darling_core", - "darling_macro", + "parity-scale-codec", ] [[package]] -name = "darling_core" -version = "0.20.8" +name = "impl-trait-for-tuples" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "fnv", - "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.52", + "syn 1.0.109", ] [[package]] -name = "darling_macro" -version = "0.20.8" +name = "indexmap" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ - "darling_core", - "quote", - "syn 2.0.52", + "equivalent", + "hashbrown", ] [[package]] -name = "data-encoding" -version = "2.5.0" +name = "indoc" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] -name = "der" -version = "0.7.8" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", + "either", ] [[package]] -name = "deranged" -version = "0.3.11" +name = "itoa" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] -name = "derivative" -version = "2.2.0" +name = "k256" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", ] [[package]] -name = "derive_arbitrary" -version = "1.3.2" +name = "keccak-asm" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", + "digest 0.10.7", + "sha3-asm", ] [[package]] -name = "derive_builder" -version = "0.20.0" +name = "lazy_static" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "derive_builder_macro", + "spin", ] [[package]] -name = "derive_builder_core" -version = "0.20.0" +name = "libc" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.52", -] +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "derive_builder_macro" -version = "0.20.0" +name = "libm" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" -dependencies = [ - "derive_builder_core", - "syn 2.0.52", -] +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] -name = "derive_more" -version = "0.99.17" +name = "linux-raw-sys" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 1.0.109", -] +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] -name = "digest" -version = "0.9.0" +name = "lock_api" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ - "generic-array", + "autocfg", + "scopeguard", ] [[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "either" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ena" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" -dependencies = [ - "log", -] - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enr" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" -dependencies = [ - "base64 0.21.7", - "bytes", - "hex", - "k256", - "log", - "rand", - "rlp", - "serde", - "sha3", - "zeroize", -] - -[[package]] -name = "enumn" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "eth-keystore" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" -dependencies = [ - "aes", - "ctr", - "digest 0.10.7", - "hex", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "rand", - "scrypt", - "serde", - "serde_json", - "sha2 0.10.8", - "sha3", - "thiserror", - "uuid", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethereum_ssz" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61ffea29f26e8249d35128a82ec8d3bd4fbc80179ea5f5e5e3daafef6a80fcb" -dependencies = [ - "ethereum-types", - "itertools 0.10.5", - "smallvec", -] - -[[package]] -name = "ethers-contract" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fceafa3578c836eeb874af87abacfb041f92b4da0a78a5edd042564b8ecdaaa" -dependencies = [ - "const-hex", - "ethers-contract-abigen", - "ethers-contract-derive", - "ethers-core", - "ethers-providers", - "futures-util", - "once_cell", - "pin-project", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "ethers-contract-abigen" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ba01fbc2331a38c429eb95d4a570166781f14290ef9fdb144278a90b5a739b" -dependencies = [ - "Inflector", - "const-hex", - "dunce", - "ethers-core", - "eyre", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "serde", - "serde_json", - "syn 2.0.52", - "toml", - "walkdir", -] - -[[package]] -name = "ethers-contract-derive" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87689dcabc0051cde10caaade298f9e9093d65f6125c14575db3fd8c669a168f" -dependencies = [ - "Inflector", - "const-hex", - "ethers-contract-abigen", - "ethers-core", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.52", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "cargo_metadata", - "chrono", - "const-hex", - "elliptic-curve", - "ethabi", - "generic-array", - "k256", - "num_enum", - "once_cell", - "open-fastrlp", - "rand", - "rlp", - "serde", - "serde_json", - "strum 0.26.1", - "syn 2.0.52", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "ethers-middleware" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f9fdf09aec667c099909d91908d5eaf9be1bd0e2500ba4172c1d28bfaa43de" -dependencies = [ - "async-trait", - "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-providers", - "ethers-signers", - "futures-channel", - "futures-locks", - "futures-util", - "instant", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-futures", - "url", -] - -[[package]] -name = "ethers-providers" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" -dependencies = [ - "async-trait", - "auto_impl", - "base64 0.21.7", - "bytes", - "const-hex", - "enr", - "ethers-core", - "futures-channel", - "futures-core", - "futures-timer", - "futures-util", - "hashers", - "http", - "instant", - "jsonwebtoken", - "once_cell", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-tungstenite", - "tracing", - "tracing-futures", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winapi", - "ws_stream_wasm", -] - -[[package]] -name = "ethers-signers" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228875491c782ad851773b652dd8ecac62cda8571d3bc32a5853644dd26766c2" -dependencies = [ - "async-trait", - "coins-bip32", - "coins-bip39", - "coins-ledger", - "const-hex", - "elliptic-curve", - "eth-keystore", - "ethers-core", - "futures-executor", - "futures-util", - "home", - "rand", - "rusoto_core", - "rusoto_kms", - "semver 1.0.22", - "sha2 0.10.8", - "spki", - "thiserror", - "tracing", - "trezor-client", -] - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" -dependencies = [ - "event-listener 5.2.0", - "pin-project-lite", -] - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "figment" -version = "0.10.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026" -dependencies = [ - "atomic", - "pear", - "serde", - "toml", - "uncased", - "version_check", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "arbitrary", - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "foundry-block-explorers" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a056d4aa33a639c0aa1e9e473c25b9b191be30cbea94b31445fac5c272418ae" -dependencies = [ - "alloy-chains", - "alloy-json-abi", - "alloy-primitives", - "foundry-compilers", - "reqwest", - "semver 1.0.22", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "foundry-cheatcodes" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-dyn-abi", - "alloy-genesis", - "alloy-json-abi", - "alloy-primitives", - "alloy-providers", - "alloy-rpc-types", - "alloy-signer", - "alloy-sol-types", - "base64 0.21.7", - "const-hex", - "eyre", - "foundry-cheatcodes-spec", - "foundry-common", - "foundry-compilers", - "foundry-config", - "foundry-evm-core", - "foundry-wallets", - "itertools 0.11.0", - "jsonpath_lib", - "k256", - "p256", - "parking_lot", - "revm", - "serde_json", - "thiserror", - "toml", - "tracing", - "walkdir", -] - -[[package]] -name = "foundry-cheatcodes-spec" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-sol-types", - "foundry-macros", - "serde", -] - -[[package]] -name = "foundry-common" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-json-rpc", - "alloy-primitives", - "alloy-providers", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-signer", - "alloy-sol-types", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", - "async-trait", - "clap", - "comfy-table", - "const-hex", - "dunce", - "ethers-core", - "ethers-middleware", - "ethers-providers", - "ethers-signers", - "eyre", - "foundry-block-explorers", - "foundry-compilers", - "foundry-config", - "glob", - "globset", - "once_cell", - "rand", - "reqwest", - "semver 1.0.22", - "serde", - "serde_json", - "tempfile", - "thiserror", - "tokio", - "tower", - "tracing", - "url", - "walkdir", - "yansi 0.5.1", -] - -[[package]] -name = "foundry-compilers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1b77c95e79bff02ddaa38426fc6809a3a438dce0e6a2eb212dac97da7c157b4" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "cfg-if", - "dirs", - "dunce", - "home", - "itertools 0.12.1", - "md-5 0.10.6", - "memmap2", - "once_cell", - "path-slash", - "rayon", - "regex", - "semver 1.0.22", - "serde", - "serde_json", - "sha2 0.10.8", - "solang-parser", - "svm-rs", - "svm-rs-builds", - "thiserror", - "tokio", - "tracing", - "walkdir", - "yansi 0.5.1", -] - -[[package]] -name = "foundry-config" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "Inflector", - "alloy-chains", - "alloy-primitives", - "dirs-next", - "dunce", - "eyre", - "figment", - "foundry-block-explorers", - "foundry-compilers", - "globset", - "number_prefix", - "once_cell", - "path-slash", - "regex", - "reqwest", - "revm-primitives", - "semver 1.0.22", - "serde", - "serde_json", - "serde_regex", - "thiserror", - "toml", - "toml_edit 0.21.1", - "tracing", - "walkdir", -] - -[[package]] -name = "foundry-evm" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-types", - "const-hex", - "eyre", - "foundry-cheatcodes", - "foundry-common", - "foundry-compilers", - "foundry-config", - "foundry-evm-core", - "foundry-evm-coverage", - "foundry-evm-fuzz", - "foundry-evm-traces", - "hashbrown", - "itertools 0.11.0", - "parking_lot", - "proptest", - "rand", - "rayon", - "revm", - "revm-inspectors", - "thiserror", - "tracing", -] - -[[package]] -name = "foundry-evm-core" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-dyn-abi", - "alloy-genesis", - "alloy-json-abi", - "alloy-primitives", - "alloy-providers", - "alloy-rpc-types", - "alloy-sol-types", - "alloy-transport", - "auto_impl", - "const-hex", - "derive_more", - "eyre", - "foundry-cheatcodes-spec", - "foundry-common", - "foundry-compilers", - "foundry-config", - "foundry-macros", - "futures", - "itertools 0.11.0", - "once_cell", - "parking_lot", - "revm", - "revm-inspectors", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "foundry-evm-coverage" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-primitives", - "eyre", - "foundry-common", - "foundry-compilers", - "foundry-evm-core", - "revm", - "semver 1.0.22", - "tracing", -] - -[[package]] -name = "foundry-evm-fuzz" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "arbitrary", - "eyre", - "foundry-common", - "foundry-compilers", - "foundry-config", - "foundry-evm-core", - "foundry-evm-coverage", - "foundry-evm-traces", - "hashbrown", - "itertools 0.11.0", - "parking_lot", - "proptest", - "rand", - "revm", - "serde", - "thiserror", - "tracing", -] - -[[package]] -name = "foundry-evm-traces" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-types", - "const-hex", - "eyre", - "foundry-block-explorers", - "foundry-common", - "foundry-compilers", - "foundry-config", - "foundry-evm-core", - "futures", - "hashbrown", - "itertools 0.11.0", - "once_cell", - "revm-inspectors", - "serde", - "tokio", - "tracing", - "yansi 0.5.1", -] - -[[package]] -name = "foundry-macros" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "foundry-wallets" -version = "0.2.0" -source = "git+https://github.com/foundry-rs/foundry?rev=0ab9e3c6fbeaa921c503c2ba1f319834b23f424b#0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" -dependencies = [ - "alloy-primitives", - "async-trait", - "clap", - "const-hex", - "derive_builder", - "ethers-core", - "ethers-providers", - "ethers-signers", - "eyre", - "foundry-common", - "foundry-config", - "itertools 0.11.0", - "rpassword", - "rusoto_core", - "rusoto_kms", - "serde", - "thiserror", - "tracing", -] - -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "futures-locks" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" -dependencies = [ - "futures-channel", - "futures-task", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" -dependencies = [ - "gloo-timers", - "send_wrapper 0.4.0", -] - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "globset" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "ahash", - "allocator-api2", - "serde", -] - -[[package]] -name = "hashers" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" -dependencies = [ - "fxhash", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hidapi-rusb" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efdc2ec354929a6e8f3c6b6923a4d97427ec2f764cfee8cd4bfe890946cdf08b" -dependencies = [ - "cc", - "libc", - "pkg-config", - "rusb", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" -dependencies = [ - "http", - "hyper", - "log", - "rustls 0.20.9", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.23.4", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls 0.21.10", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "2.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "indoc" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" - -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "interprocess" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb" -dependencies = [ - "blocking", - "cfg-if", - "futures-core", - "futures-io", - "intmap", - "libc", - "once_cell", - "rustc_version 0.4.0", - "spinning", - "thiserror", - "to_method", - "tokio", - "winapi", -] - -[[package]] -name = "intmap" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9" - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "jobserver" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonpath_lib" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" -dependencies = [ - "log", - "serde", - "serde_json", -] - -[[package]] -name = "jsonwebtoken" -version = "8.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" -dependencies = [ - "base64 0.21.7", - "pem", - "ring 0.16.20", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2 0.10.8", - "signature", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak-asm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - -[[package]] -name = "lalrpop" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" -dependencies = [ - "ascii-canvas", - "bit-set", - "ena", - "itertools 0.11.0", - "lalrpop-util", - "petgraph", - "regex", - "regex-syntax", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", - "walkdir", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin 0.5.2", -] - -[[package]] -name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.2", - "libc", - "redox_syscall", -] - -[[package]] -name = "libusb1-sys" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "memmap2" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", - "pin-utils", -] - -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2 0.10.8", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" -dependencies = [ - "proc-macro-crate 2.0.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "path-slash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", - "password-hash", - "sha2 0.10.8", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", -] - -[[package]] -name = "pear" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi 1.0.0", -] - -[[package]] -name = "pear_codegen" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "pem" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" -dependencies = [ - "base64 0.13.1", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "prettyplease" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" -dependencies = [ - "proc-macro2", - "syn 2.0.52", -] - -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", - "version_check", - "yansi 1.0.0", -] - -[[package]] -name = "proptest" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.4.2", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "proptest-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "protobuf" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65f4a8ec18723a734e5dc09c173e0abf9690432da5340285d536edcb4dac190" -dependencies = [ - "once_cell", - "protobuf-support", - "thiserror", -] - -[[package]] -name = "protobuf-support" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6872f4d4f4b98303239a2b5838f5bbbb77b01ffc892d627957f37a22d7cfe69c" -dependencies = [ - "thiserror", -] - -[[package]] -name = "pyo3" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" -dependencies = [ - "cfg-if", - "indoc", - "libc", - "memoffset 0.9.0", - "parking_lot", - "pyo3-build-config", - "pyo3-ffi", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" -dependencies = [ - "once_cell", - "target-lexicon", -] - -[[package]] -name = "pyo3-ffi" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" -dependencies = [ - "libc", - "pyo3-build-config", -] - -[[package]] -name = "pyo3-macros" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" -dependencies = [ - "proc-macro2", - "pyo3-macros-backend", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "pyrevm" -version = "0.2.0" -dependencies = [ - "foundry-evm", - "pyo3", - "revm", - "revm-interpreter", - "ruint", - "tracing", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "reqwest" -version = "0.11.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls 0.24.2", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.10", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-rustls 0.24.1", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "revm" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d35316fc02d99e42831356c71e882f5d385c77b78f64a44ae82f2f9a4b8b72f" -dependencies = [ - "auto_impl", - "cfg-if", - "revm-interpreter", - "revm-precompile", - "serde", - "serde_json", -] - -[[package]] -name = "revm-inspectors" -version = "0.1.0" -source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=5d560be#5d560be4cf022912f4f53f4e5ea71f81253b3c3d" -dependencies = [ - "alloy-primitives", - "alloy-rpc-trace-types", - "alloy-rpc-types", - "alloy-sol-types", - "anstyle", - "colorchoice", - "revm", - "serde", -] - -[[package]] -name = "revm-interpreter" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fa10c2dc1e8f4934bdc763a2c09371bcec29e50c22e55e3eb325ee0cba09064" -dependencies = [ - "revm-primitives", - "serde", -] - -[[package]] -name = "revm-precompile" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db828d49d329560a70809d9d1fa0c74695edb49f50c5332db3eb24483076deac" -dependencies = [ - "aurora-engine-modexp", - "c-kzg", - "k256", - "once_cell", - "revm-primitives", - "ripemd", - "secp256k1", - "sha2 0.10.8", - "substrate-bn", -] - -[[package]] -name = "revm-primitives" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecd125aad58e135e2ca5771ed6e4e7b1f05fa3a64e0dfb9cc643b7a800a8435" -dependencies = [ - "alloy-primitives", - "auto_impl", - "bitflags 2.4.2", - "bitvec", - "c-kzg", - "cfg-if", - "derive_more", - "enumn", - "hashbrown", - "hex", - "once_cell", - "serde", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac 0.12.1", - "subtle", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.52.0", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rpassword" -version = "7.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" -dependencies = [ - "libc", - "rtoolbox", - "windows-sys 0.48.0", -] - -[[package]] -name = "rtoolbox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "ruint" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b1d9521f889713d1221270fdd63370feca7e5c71a18745343402fa86e4f04f" -dependencies = [ - "alloy-rlp", - "arbitrary", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp", - "num-bigint", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "pyo3", - "rand", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" - -[[package]] -name = "rusb" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fff149b6033f25e825cbb7b2c625a11ee8e6dac09264d49beb125e39aa97bf" -dependencies = [ - "libc", - "libusb1-sys", -] - -[[package]] -name = "rusoto_core" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db30db44ea73551326269adcf7a2169428a054f14faf9e1768f2163494f2fa2" -dependencies = [ - "async-trait", - "base64 0.13.1", - "bytes", - "crc32fast", - "futures", - "http", - "hyper", - "hyper-rustls 0.23.2", - "lazy_static", - "log", - "rusoto_credential", - "rusoto_signature", - "rustc_version 0.4.0", - "serde", - "serde_json", - "tokio", - "xml-rs", -] - -[[package]] -name = "rusoto_credential" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0a6c13db5aad6047b6a44ef023dbbc21a056b6dab5be3b79ce4283d5c02d05" -dependencies = [ - "async-trait", - "chrono", - "dirs-next", - "futures", - "hyper", - "serde", - "serde_json", - "shlex", - "tokio", - "zeroize", -] - -[[package]] -name = "rusoto_kms" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1fc19cfcfd9f6b2f96e36d5b0dddda9004d2cbfc2d17543e3b9f10cc38fce8" -dependencies = [ - "async-trait", - "bytes", - "futures", - "rusoto_core", - "serde", - "serde_json", -] - -[[package]] -name = "rusoto_signature" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ae95491c8b4847931e291b151127eccd6ff8ca13f33603eb3d0035ecb05272" -dependencies = [ - "base64 0.13.1", - "bytes", - "chrono", - "digest 0.9.0", - "futures", - "hex", - "hmac 0.11.0", - "http", - "hyper", - "log", - "md-5 0.9.1", - "percent-encoding", - "pin-project-lite", - "rusoto_credential", - "rustc_version 0.4.0", - "serde", - "sha2 0.9.9", - "tokio", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.22", -] - -[[package]] -name = "rustix" -version = "0.38.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" -dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring 0.17.8", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" - -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scale-info" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scrypt" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" -dependencies = [ - "hmac 0.12.1", - "pbkdf2 0.11.0", - "salsa20", - "sha2 0.10.8", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" -dependencies = [ - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" -dependencies = [ - "cc", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" -dependencies = [ - "serde", -] - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "send_wrapper" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - -[[package]] -name = "serde" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "serde_json" -version = "1.0.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_regex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" -dependencies = [ - "regex", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "sha3-asm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" -dependencies = [ - "cc", - "cfg-if", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "memchr" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] -name = "signature" -version = "2.2.0" +name = "memoffset" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ - "digest 0.10.7", - "rand_core", + "autocfg", ] [[package]] -name = "simple_asn1" -version = "0.6.2" +name = "num" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", "num-traits", - "thiserror", - "time", ] [[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" +name = "num-bigint" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", + "num-integer", + "num-traits", ] [[package]] -name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" - -[[package]] -name = "socket2" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "solang-parser" -version = "0.3.3" +name = "num-complex" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ - "itertools 0.11.0", - "lalrpop", - "lalrpop-util", - "phf", - "thiserror", - "unicode-xid", + "num-traits", ] [[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spinning" -version = "0.1.0" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d4f0e86297cad2658d92a707320d87bf4e6ae1050287f51d19b67ef3f153a7b" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "lock_api", + "num-traits", ] [[package]] -name = "spki" -version = "0.7.3" +name = "num-iter" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ - "base64ct", - "der", + "autocfg", + "num-integer", + "num-traits", ] [[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "string_cache" -version = "0.8.7" +name = "num-rational" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared 0.10.0", - "precomputed-hash", + "autocfg", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] -name = "strsim" -version = "0.10.0" +name = "num-traits" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", + "libm", +] [[package]] -name = "strsim" -version = "0.11.0" +name = "num_cpus" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] [[package]] -name = "strum" -version = "0.25.0" +name = "once_cell" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "strum" -version = "0.26.1" +name = "parity-scale-codec" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ - "strum_macros 0.26.1", + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", ] [[package]] -name = "strum_macros" -version = "0.25.3" +name = "parity-scale-codec-derive" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "heck", + "proc-macro-crate", "proc-macro2", "quote", - "rustversion", - "syn 2.0.52", + "syn 1.0.109", ] [[package]] -name = "strum_macros" -version = "0.26.1" +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.52", + "lock_api", + "parking_lot_core", ] [[package]] -name = "substrate-bn" -version = "0.6.0" +name = "parking_lot_core" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand", - "rustc-hex", + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", ] [[package]] -name = "subtle" -version = "2.4.1" +name = "paste" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] -name = "svm-rs" -version = "0.3.5" +name = "pest" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" dependencies = [ - "dirs", - "fs2", - "hex", - "once_cell", - "reqwest", - "semver 1.0.22", - "serde", - "serde_json", - "sha2 0.10.8", + "memchr", "thiserror", - "url", - "zip", + "ucd-trie", ] [[package]] -name = "svm-rs-builds" -version = "0.3.5" +name = "pin-project-lite" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8d3c94c4d3337336f58493471b98d712c267c66977b0fbe48efd6cbf69ffd0" -dependencies = [ - "build_const", - "hex", - "semver 1.0.22", - "serde_json", - "svm-rs", -] +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] -name = "syn" -version = "1.0.109" +name = "pkcs8" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "der", + "spki", ] [[package]] -name = "syn" -version = "2.0.52" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "syn-solidity" -version = "0.6.4" +name = "primitive-types" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.52", + "fixed-hash", + "impl-codec", + "uint", ] [[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "system-configuration" -version = "0.5.1" +name = "proc-macro-crate" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", + "toml_edit", ] [[package]] -name = "system-configuration-sys" -version = "0.5.0" +name = "proc-macro2" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ - "core-foundation-sys", - "libc", + "unicode-ident", ] [[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "target-lexicon" -version = "0.12.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" - -[[package]] -name = "tempfile" -version = "3.10.1" +name = "proptest" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", + "bit-set", + "bit-vec", + "bitflags 2.4.2", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", ] [[package]] -name = "term" -version = "0.7.0" +name = "pyo3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" dependencies = [ - "dirs-next", - "rustversion", - "winapi", + "cfg-if", + "indoc", + "libc", + "memoffset", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", ] [[package]] -name = "terminal_size" -version = "0.3.0" +name = "pyo3-build-config" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" dependencies = [ - "rustix", - "windows-sys 0.48.0", + "once_cell", + "target-lexicon", ] [[package]] -name = "thiserror" -version = "1.0.57" +name = "pyo3-ffi" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" dependencies = [ - "thiserror-impl", + "libc", + "pyo3-build-config", ] [[package]] -name = "thiserror-impl" -version = "1.0.57" +name = "pyo3-macros" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" dependencies = [ "proc-macro2", + "pyo3-macros-backend", "quote", - "syn 2.0.52", + "syn 1.0.109", ] [[package]] -name = "threadpool" -version = "1.8.1" +name = "pyo3-macros-backend" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" dependencies = [ - "num_cpus", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "time" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +name = "pyrevm" +version = "0.2.0" dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", + "pyo3", + "revm", + "revm-interpreter", + "ruint", + "tracing", ] [[package]] -name = "time-core" -version = "0.1.2" +name = "quick-error" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] -name = "time-macros" -version = "0.2.17" +name = "quote" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ - "num-conv", - "time-core", + "proc-macro2", ] [[package]] -name = "tiny-keccak" -version = "2.0.2" +name = "radium" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] -name = "tinyvec" -version = "1.6.0" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "tinyvec_macros", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "to_method" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" - -[[package]] -name = "tokio" -version = "1.36.0" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", + "ppv-lite86", + "rand_core", ] [[package]] -name = "tokio-macros" -version = "2.2.0" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", + "getrandom", ] [[package]] -name = "tokio-rustls" -version = "0.23.4" +name = "rand_xorshift" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", + "rand_core", ] [[package]] -name = "tokio-rustls" -version = "0.24.1" +name = "redox_syscall" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "rustls 0.21.10", - "tokio", + "bitflags 1.3.2", ] [[package]] -name = "tokio-tungstenite" -version = "0.20.1" +name = "regex-syntax" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "rustls 0.21.10", - "tokio", - "tokio-rustls 0.24.1", - "tungstenite", - "webpki-roots", -] +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] -name = "tokio-util" -version = "0.7.10" +name = "revm" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "217d21144d329f21d5245b8e6a46e0d6d0a527d9917d7a087f225b161e529169" dependencies = [ - "bytes", - "futures-core", - "futures-io", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", + "auto_impl", + "cfg-if", + "dyn-clone", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", ] [[package]] -name = "toml" -version = "0.8.10" +name = "revm-interpreter" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "776848391ed76d5103ca1aa1632cd21b521e2870afb30b63723da862d69efd0f" dependencies = [ - "indexmap", + "revm-primitives", "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.6", ] [[package]] -name = "toml_datetime" -version = "0.6.5" +name = "revm-precompile" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "e3fd1856a7cb09197a02669d779e1afb5a627b0888a24814ba2b6a1ad4c3ff8d" dependencies = [ - "serde", + "aurora-engine-modexp", + "c-kzg", + "k256", + "once_cell", + "revm-primitives", + "ripemd", + "secp256k1", + "sha2", + "substrate-bn", ] [[package]] -name = "toml_edit" -version = "0.19.15" +name = "revm-primitives" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "2a4d7d3e793e907dc0797a9d3b43abfdf5226d133855214db9bd27d4cee33ebd" dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", + "alloy-primitives", + "auto_impl", + "bitflags 2.4.2", + "bitvec", + "c-kzg", + "cfg-if", + "derive_more", + "dyn-clone", + "enumn", + "hashbrown", + "hex", + "once_cell", + "serde", ] [[package]] -name = "toml_edit" -version = "0.20.7" +name = "rfc6979" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", + "hmac", + "subtle", ] [[package]] -name = "toml_edit" -version = "0.21.1" +name = "ripemd" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", + "digest 0.10.7", ] [[package]] -name = "toml_edit" -version = "0.22.6" +name = "rlp" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.5", + "bytes", + "rustc-hex", ] [[package]] -name = "tower" -version = "0.4.13" +name = "ruint" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "49b1d9521f889713d1221270fdd63370feca7e5c71a18745343402fa86e4f04f" dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "pyo3", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", ] [[package]] -name = "tower-layer" -version = "0.3.2" +name = "ruint-macro" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] -name = "tower-service" -version = "0.3.2" +name = "rustc-hex" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] -name = "tracing" -version = "0.1.40" +name = "rustc_version" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", + "semver 0.11.0", ] [[package]] -name = "tracing-attributes" -version = "0.1.27" +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", + "semver 1.0.22", ] [[package]] -name = "tracing-core" -version = "0.1.32" +name = "rustix" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "once_cell", + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] -name = "tracing-futures" -version = "0.2.5" +name = "rusty-fork" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ - "pin-project", - "tracing", + "fnv", + "quick-error", + "tempfile", + "wait-timeout", ] [[package]] -name = "trezor-client" -version = "0.1.3" +name = "ryu" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62c95b37f6c769bd65a0d0beb8b2b003e72998003b896a616a6777c645c05ed" -dependencies = [ - "byteorder", - "hex", - "protobuf", - "rusb", - "thiserror", - "tracing", -] +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] -name = "try-lock" -version = "0.2.5" +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "tungstenite" -version = "0.20.1" +name = "sec1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand", - "rustls 0.21.10", - "sha1", - "thiserror", - "url", - "utf-8", + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", ] [[package]] -name = "typenum" -version = "1.17.0" +name = "secp256k1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] [[package]] -name = "ucd-trie" -version = "0.1.6" +name = "secp256k1-sys" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] [[package]] -name = "uint" -version = "0.9.5" +name = "semver" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "arbitrary", - "byteorder", - "crunchy", - "hex", - "static_assertions", + "semver-parser", ] [[package]] -name = "unarray" -version = "0.1.4" +name = "semver" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] [[package]] -name = "uncased" -version = "0.9.10" +name = "serde" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ - "version_check", + "serde_derive", ] [[package]] -name = "unicase" -version = "2.7.0" +name = "serde_derive" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ - "version_check", + "proc-macro2", + "quote", + "syn 2.0.52", ] [[package]] -name = "unicode-bidi" -version = "0.3.15" +name = "serde_json" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "sha2" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] [[package]] -name = "unicode-normalization" -version = "0.1.23" +name = "sha3-asm" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" dependencies = [ - "tinyvec", + "cc", + "cfg-if", ] [[package]] -name = "unicode-width" -version = "0.1.11" +name = "signature" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] [[package]] -name = "unicode-xid" -version = "0.2.4" +name = "smallvec" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] -name = "unindent" -version = "0.1.11" +name = "spin" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "untrusted" -version = "0.7.1" +name = "spki" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] [[package]] -name = "untrusted" -version = "0.9.0" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "url" -version = "2.5.0" +name = "substrate-bn" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", + "byteorder", + "crunchy", + "lazy_static", + "rand", + "rustc-hex", ] [[package]] -name = "utf-8" -version = "0.7.6" +name = "subtle" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] -name = "utf8parse" -version = "0.2.1" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] -name = "uuid" -version = "0.8.2" +name = "syn" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ - "getrandom", - "serde", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "valuable" -version = "0.1.0" +name = "tap" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "vcpkg" -version = "0.2.15" +name = "target-lexicon" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] -name = "version_check" -version = "0.9.4" +name = "tempfile" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] [[package]] -name = "wait-timeout" -version = "0.2.0" +name = "thiserror" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ - "libc", + "thiserror-impl", ] [[package]] -name = "walkdir" -version = "2.5.0" +name = "thiserror-impl" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ - "same-file", - "winapi-util", + "proc-macro2", + "quote", + "syn 2.0.52", ] [[package]] -name = "want" -version = "0.3.1" +name = "threadpool" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" dependencies = [ - "try-lock", + "num_cpus", ] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "tiny-keccak" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] [[package]] -name = "wasm-bindgen" -version = "0.2.92" +name = "toml_datetime" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" +name = "toml_edit" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.52", - "wasm-bindgen-shared", + "indexmap", + "toml_datetime", + "winnow", ] [[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" +name = "tracing" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", + "pin-project-lite", + "tracing-attributes", + "tracing-core", ] [[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" +name = "tracing-attributes" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ + "proc-macro2", "quote", - "wasm-bindgen-macro-support", + "syn 2.0.52", ] [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", - "wasm-bindgen-backend", - "wasm-bindgen-shared", + "once_cell", ] [[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] -name = "web-sys" -version = "0.3.69" +name = "ucd-trie" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] -name = "webpki" -version = "0.22.4" +name = "uint" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "byteorder", + "crunchy", + "hex", + "static_assertions", ] [[package]] -name = "webpki-roots" -version = "0.25.4" +name = "unarray" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] -name = "winapi" -version = "0.3.9" +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "unindent" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] -name = "winapi-util" -version = "0.1.6" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "windows-core" -version = "0.52.0" +name = "wait-timeout" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ - "windows-targets 0.52.4", + "libc", ] [[package]] -name = "windows-sys" -version = "0.48.0" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "windows-sys" @@ -5980,44 +1826,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winnow" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "ws_stream_wasm" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" -dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version 0.4.0", - "send_wrapper 0.6.0", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "wyz" version = "0.5.1" @@ -6027,24 +1835,6 @@ dependencies = [ "tap", ] -[[package]] -name = "xml-rs" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - -[[package]] -name = "yansi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2861d76f58ec8fc95708b9b1e417f7b12fd72ad33c01fa6886707092dea0d3" - [[package]] name = "zerocopy" version = "0.7.32" @@ -6084,52 +1874,3 @@ dependencies = [ "quote", "syn 2.0.52", ] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "sha1", - "time", - "zstd", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml index cd2f486..975f3ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,8 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -foundry-evm = { git = "https://github.com/foundry-rs/foundry", rev = "0ab9e3c6fbeaa921c503c2ba1f319834b23f424b" } -revm = "6.1" -revm-interpreter = "=3.1" +revm = "7.1.0" +revm-interpreter = "3.3.0" tracing = "0.1" pyo3 = { version = "0.19", features = ["extension-module"] } ruint = { version = "1.10", features = ["pyo3"] } diff --git a/pytest/test.py b/pytest/test.py index efe13c4..b576c19 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -80,10 +80,14 @@ def test_balances(): # Give ether AMT = 10000 - evm.set_balance(address, AMT) + try: + evm.set_balance(address, AMT) - assert evm.get_balance(address) == AMT - assert evm.basic(address).balance == AMT + assert evm.get_balance(address) == AMT + assert evm.basic(address).balance == AMT + except Exception as e: + accs = {k: (v.balance, any(v.code)) for k, v in evm.get_accounts().items()} + raise Exception(accs) from e def test_call_raw(): @@ -147,4 +151,4 @@ def test_call_empty_result(): assert int.from_bytes(balance, "big") == 10000 except Exception as e: accs = {k: (v.balance, any(v.code)) for k, v in evm.get_accounts().items()} - raise Exception(f"{e} - {accs}") from e + raise Exception(accs) from e diff --git a/src/empty_db_wrapper.rs b/src/empty_db_wrapper.rs new file mode 100644 index 0000000..7f43dd1 --- /dev/null +++ b/src/empty_db_wrapper.rs @@ -0,0 +1,35 @@ +use std::convert::Infallible; +use revm::{ + Database, + db::{DatabaseRef, EmptyDB}, + primitives::{AccountInfo, Bytecode}, +}; +use revm::primitives::{Address, B256, U256}; + +/// An empty database that always returns default values when queried. +/// This will also _always_ return `Some(AccountInfo)`: +/// Copied from Foundry: https://github.com/foundry-rs/foundry/blob/9e3ab9b3aff21c6e5ef/crates/evm/core/src/backend/in_memory_db.rs#L83-L92 + +#[derive(Clone, Debug, Default)] +pub struct EmptyDBWrapper(EmptyDB); + +impl DatabaseRef for EmptyDBWrapper { + type Error = Infallible; + + fn basic_ref(&self, _address: Address) -> Result, Self::Error> { + // Note: this will always return `Some(AccountInfo)`, for the reason explained above + Ok(Some(AccountInfo::default())) + } + + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + Ok(self.0.code_by_hash_ref(code_hash)?) + } + fn storage_ref(&self, address: Address, index: U256) -> Result { + Ok(self.0.storage_ref(address, index)?) + } + + fn block_hash_ref(&self, number: U256) -> Result { + Ok(self.0.block_hash_ref(number)?) + } +} + diff --git a/src/evm.rs b/src/evm.rs index 02dc4dc..8223fef 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,23 +1,23 @@ use std::collections::HashMap; use std::fmt::Debug; -use std::hash::Hash; use pyo3::exceptions::PyRuntimeError; use pyo3::prelude::*; -use revm::{Database, DatabaseCommit, Evm, InMemoryDB, primitives::U256}; -use revm::db::{CacheDB}; +use revm::{Database, DatabaseCommit, DatabaseRef, Evm, InMemoryDB, primitives::U256}; +use revm::db::CacheDB; use revm::precompile::{Address, Bytes}; use revm::precompile::B256; -use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; -use revm::primitives::ExecutionResult::{Success}; +use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, AccountInfo as RevmAccountInfo, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::ExecutionResult::Success; use tracing::{trace, warn}; use crate::{ types::{AccountInfo, Env}, utils::addr, }; +use crate::empty_db_wrapper::EmptyDBWrapper; -type DB = CacheDB; +type DB = CacheDB; #[derive(Clone, Debug)] #[pyclass] @@ -50,19 +50,16 @@ fn pyerr(err: T) -> PyErr { #[pymethods] impl EVM { #[new] - #[pyo3(signature = (env=None, gas_limit=18446744073709551615, tracing=false, spec_id="LATEST"))] + #[pyo3(signature = (env=None, gas_limit=18446744073709551615, tracing=false, spec_id="SHANGHAI"))] fn new( env: Option, gas_limit: u64, tracing: bool, spec_id: &str, ) -> PyResult { - // let db = CacheDB::new(EmptyDB::default()); - let db = CacheDB::new(Default::default()); - // let db = CacheDB::new(InMemoryDB::new(EmptyDB::new())); Ok(EVM { - db, - env: env.or(Some(Env::default())).unwrap().into(), + db: DB::default(), + env: env.unwrap_or_default().into(), gas_limit: U256::from(gas_limit), handler_cfg: HandlerCfg::new(SpecId::from(spec_id)), }) @@ -70,14 +67,14 @@ impl EVM { /// Get basic account information. fn basic(&mut self, address: &str) -> PyResult { - let db_account = self.db.load_account(addr(address)?).map_err(pyerr)?; - Ok(db_account.info.clone().into()) + let db_account = self.db.basic_ref(addr(address)?).map_err(pyerr)?; + Ok(db_account.unwrap_or_default().into()) } - fn get_accounts(&self) -> PyResult> {context - self.db - .journaled_state - .load_account(tx_caller, &mut context.evm.inner.db)?; + fn get_accounts(&self) -> PyResult> { + // self.db + // .journaled_state + // .load_account(tx_caller, &mut context.evm.inner.db)?; Ok(self.db.accounts.iter().map( |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) ).collect()) @@ -106,7 +103,9 @@ impl EVM { address: &str, info: AccountInfo, ) -> PyResult<()> { - self.db.insert_account_info(addr(address)?, info.into()); + let info = RevmAccountInfo::from(info); + self.db.insert_account_info(addr(address)?, info.clone()); + assert_eq!(self.db.basic(addr(address)?).unwrap().unwrap().balance, info.balance); Ok(()) } @@ -117,6 +116,7 @@ impl EVM { info.balance = balance; self.db.insert_account_info(target, info.clone()); assert_eq!(self.db.load_account(target).map(|a| a.info.clone()).map_err(pyerr)?, info); + // assert_eq!(self.db.basic(target).map(|a| a.unwrap_or_default().balance).map_err(pyerr)?, balance); Ok(()) } @@ -124,6 +124,8 @@ impl EVM { fn get_balance(&mut self, address: &str) -> PyResult { // Ok(self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) let acc = self.db.load_account(addr(address)?).map_err(pyerr)?; + // let db_account = self.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); + // assert_eq!(db_account.balance, acc.info.balance); Ok(acc.info.balance) } @@ -235,7 +237,7 @@ fn deploy_with_env( let ResultAndState { result, state } = Evm::builder() - .with_ref_db(&db) + .with_ref_db(db) .with_env_with_handler_cfg(env) .build() .transact() diff --git a/src/lib.rs b/src/lib.rs index d10318f..b90cb4b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ mod evm; pub use evm::EVM; mod utils; +mod empty_db_wrapper; #[pymodule] fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { From 28766d7e0ea35481214fe0efa6ec1d217022bb41 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Mon, 18 Mar 2024 14:03:10 +0100 Subject: [PATCH 05/33] Implement forking --- Cargo.lock | 1491 ++++++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- pyrevm.pyi | 48 +- pytest/test.py | 52 +- src/empty_db_wrapper.rs | 4 +- src/evm.rs | 154 ++-- src/utils.rs | 17 +- 7 files changed, 1614 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8088c71..c46649d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.8.11" @@ -14,6 +29,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.16" @@ -182,6 +206,28 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-trait" +version = "0.1.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.0", +] + [[package]] name = "aurora-engine-modexp" version = "1.0.0" @@ -209,12 +255,39 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64ct" version = "1.6.0" @@ -247,6 +320,9 @@ name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +dependencies = [ + "serde", +] [[package]] name = "bitvec" @@ -256,6 +332,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -281,6 +358,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -298,6 +381,9 @@ name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] [[package]] name = "c-kzg" @@ -325,6 +411,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +dependencies = [ + "num-traits", +] + [[package]] name = "const-hex" version = "1.11.1" @@ -350,6 +445,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -387,6 +498,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + [[package]] name = "der" version = "0.7.8" @@ -397,6 +514,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -487,6 +613,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enr" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" +dependencies = [ + "base64 0.21.7", + "bytes", + "hex", + "k256", + "log", + "rand", + "rlp", + "serde", + "sha3", + "zeroize", +] + [[package]] name = "enumn" version = "0.1.13" @@ -511,7 +664,120 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers-core" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array", + "k256", + "num_enum", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-providers" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.7", + "bytes", + "const-hex", + "enr", + "ethers-core", + "futures-channel", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "http", + "instant", + "jsonwebtoken", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", ] [[package]] @@ -559,12 +825,129 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +dependencies = [ + "gloo-timers", + "send_wrapper 0.4.0", +] + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -587,12 +970,30 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -604,6 +1005,25 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -612,8 +1032,24 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", + "serde", +] + +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -625,6 +1061,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-literal" @@ -642,17 +1081,117 @@ dependencies = [ ] [[package]] -name = "impl-codec" -version = "0.6.0" +name = "http" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "parity-scale-codec", + "bytes", + "fnv", + "itoa", ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ @@ -677,6 +1216,21 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "itertools" version = "0.10.5" @@ -692,6 +1246,29 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "8.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +dependencies = [ + "base64 0.21.7", + "pem", + "ring 0.16.20", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "k256" version = "0.13.3" @@ -706,6 +1283,15 @@ dependencies = [ "signature", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "keccak-asm" version = "0.1.0" @@ -722,7 +1308,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] [[package]] @@ -753,6 +1339,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "memchr" version = "2.7.1" @@ -768,6 +1360,32 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "num" version = "0.4.1" @@ -802,6 +1420,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.46" @@ -854,12 +1478,67 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate 2.0.0", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "parity-scale-codec" version = "3.6.9" @@ -880,7 +1559,7 @@ version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 1.0.109", @@ -915,6 +1594,21 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pest" version = "2.7.8" @@ -926,12 +1620,48 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.0", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkcs8" version = "0.10.2" @@ -942,6 +1672,12 @@ dependencies = [ "spki", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -956,16 +1692,29 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", "uint", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + [[package]] name = "proc-macro-crate" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_edit", + "toml_edit 0.20.7", ] [[package]] @@ -1061,6 +1810,8 @@ dependencies = [ name = "pyrevm" version = "0.2.0" dependencies = [ + "ethers-core", + "ethers-providers", "pyo3", "revm", "revm-interpreter", @@ -1137,12 +1888,76 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "reqwest" +version = "0.11.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + [[package]] name = "revm" version = "7.1.0" @@ -1152,10 +1967,13 @@ dependencies = [ "auto_impl", "cfg-if", "dyn-clone", + "ethers-core", + "ethers-providers", "revm-interpreter", "revm-precompile", "serde", "serde_json", + "tokio", ] [[package]] @@ -1216,6 +2034,36 @@ dependencies = [ "subtle", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -1232,14 +2080,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ruint" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b1d9521f889713d1221270fdd63370feca7e5c71a18745343402fa86e4f04f" +checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -1266,6 +2126,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -1300,33 +2166,104 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] -name = "rusty-fork" -version = "0.3.0" +name = "rustls" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", + "log", + "ring 0.17.8", + "rustls-webpki", + "sct", ] [[package]] -name = "ryu" -version = "1.0.17" +name = "rustls-pemfile" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "rustls-webpki" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "scale-info" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef2175c2907e7c8bc0a9c3f86aeb5ec1f3b275300ad58a44d0c3ae379a5e52e" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b8eb8fd61c5cdd3390d9b2132300a7e7618955b98b8416f118c1b4e144f" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + [[package]] name = "sec1" version = "0.7.3" @@ -1383,6 +2320,18 @@ dependencies = [ "pest", ] +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.197" @@ -1415,6 +2364,29 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.10.8" @@ -1426,6 +2398,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "sha3-asm" version = "0.1.0" @@ -1446,18 +2428,55 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.7.3" @@ -1474,6 +2493,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.52", +] + [[package]] name = "substrate-bn" version = "0.6.0" @@ -1515,6 +2556,33 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -1536,7 +2604,7 @@ dependencies = [ "cfg-if", "fastrand", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1568,6 +2636,37 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1577,12 +2676,105 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "toml_datetime" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "toml_edit" version = "0.20.7" @@ -1594,6 +2786,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" @@ -1625,6 +2823,42 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "typenum" version = "1.17.0" @@ -1655,18 +2889,68 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "unindent" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "valuable" version = "0.1.0" @@ -1688,12 +2972,134 @@ dependencies = [ "libc", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.52", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1826,6 +3232,35 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.0", + "send_wrapper 0.6.0", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 975f3ad..9cad66b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,12 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -revm = "7.1.0" +revm = { "version"="7.1.0", features=["ethersdb", "serde"] } revm-interpreter = "3.3.0" tracing = "0.1" pyo3 = { version = "0.19", features = ["extension-module"] } ruint = { version = "1.10", features = ["pyo3"] } + +# needed for ethersdb +ethers-core = "2.0.14" +ethers-providers = "2.0.14" diff --git a/pyrevm.pyi b/pyrevm.pyi index 0208720..386d6e4 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -1,4 +1,5 @@ -from typing import Optional, Type +from typing import Optional, Type, Tuple + class CfgEnv: def __new__(cls: Type["CfgEnv"]) -> "CfgEnv": ... @@ -15,21 +16,6 @@ class BlockEnv: gas_limit: Optional[int] = None, ) -> "BlockEnv": ... - @property - def number(self: "BlockEnv") -> int: ... - @property - def coinbase(self: "BlockEnv") -> str: ... - @property - def timestamp(self: "BlockEnv") -> int: ... - @property - def difficulty(self: "BlockEnv") -> int: ... - @property - def prevrandao(self: "BlockEnv") -> bytes: ... - @property - def basefee(self: "BlockEnv") -> int: ... - @property - def gas_limit(self: "BlockEnv") -> int: ... - class TxEnv: def __new__( cls: Type["TxEnv"], @@ -84,11 +70,11 @@ class EVM: def __new__( cls: Type["EVM"], env: Optional[Env] = None, - # fork_url: Optional[str] = None, - # fork_block_number: Optional[int] = None, + fork_url: Optional[str] = None, + fork_block_number: Optional[int] = None, gas_limit: int = 2**64 - 1, tracing: bool = False, - spec_id="latest", + spec_id="SHANGHAI", ) -> "EVM": """ Creates a new EVM instance. @@ -98,11 +84,6 @@ class EVM: :param spec_id: The spec ID. """ - def get_accounts(self) -> dict[str, AccountInfo]: - """ - :return: a dictionary of account addresses to account info - """ - def basic(self: "EVM", address: str) -> AccountInfo: """ Returns the basic account info for the given address. @@ -139,14 +120,14 @@ class EVM: to: str, calldata: Optional[bytes] = None, value: Optional[int] = None, - ) -> bytes: + ) -> Tuple[bytes, dict[str, AccountInfo]]: """ Processes a raw call, without committing the result to the state. :param caller: The address of the caller. :param to: The address of the callee. :param calldata: The calldata. :param value: The value. - :return: The return data. + :return: The return data and a list of changes to the state. """ def deploy( @@ -155,5 +136,16 @@ class EVM: code: bytes, value: Optional[int] = None, ) -> str: ... - def get_balance(self: "EVM", address: str) -> int: ... - def set_balance(self: "EVM", address: str, balance: int) -> None: ... + def get_balance(self: "EVM", address: str) -> int: + """ + Returns the balance of the given address. + :param address: The address. + :return: The balance. + """ + + def set_balance(self: "EVM", address: str, balance: int) -> None + """ + Sets the balance of the given address. + :param address: The address. + :param balance: The balance. + """ diff --git a/pytest/test.py b/pytest/test.py index b576c19..4d84e9e 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -25,7 +25,7 @@ def encode_uint(num: int) -> str: def encode_address(address: str) -> str: return f'{"0" * 24}{address[2:]}' -@pytest.mark.skip("Fork not supported") + def test_revm(): # set up an evm evm = EVM( @@ -80,14 +80,10 @@ def test_balances(): # Give ether AMT = 10000 - try: - evm.set_balance(address, AMT) + evm.set_balance(address, AMT) - assert evm.get_balance(address) == AMT - assert evm.basic(address).balance == AMT - except Exception as e: - accs = {k: (v.balance, any(v.code)) for k, v in evm.get_accounts().items()} - raise Exception(accs) from e + assert evm.get_balance(address) == AMT + assert evm.basic(address).balance == AMT def test_call_raw(): @@ -97,7 +93,7 @@ def test_call_raw(): assert evm.basic(address).code == info.code # mulDiv() -> 64 * 8 / 2 - result = evm.call_raw( + result, changes = evm.call_raw( caller=address2, to=address, calldata=bytes.fromhex( @@ -106,6 +102,8 @@ def test_call_raw(): ) assert int.from_bytes(result, "big") == 256 + assert changes[address].nonce == 0 + assert changes[address2].nonce == 1 def test_call_committing(): @@ -132,23 +130,19 @@ def test_call_empty_result(): evm.set_balance(address2, 10000) - try: - deposit = evm.call_raw_committing( - caller=address2, - to=address, - value=10000, - calldata=bytes.fromhex("d0e30db0"), - ) - - assert deposit == [] - - balance = evm.call_raw( - caller=address2, - to=address, - calldata=bytes.fromhex("70a08231" + encode_address(address2)), - ) - - assert int.from_bytes(balance, "big") == 10000 - except Exception as e: - accs = {k: (v.balance, any(v.code)) for k, v in evm.get_accounts().items()} - raise Exception(accs) from e + deposit = evm.call_raw_committing( + caller=address2, + to=address, + value=10000, + calldata=bytes.fromhex("d0e30db0"), + ) + + assert deposit == [] + + balance, _ = evm.call_raw( + caller=address2, + to=address, + calldata=bytes.fromhex("70a08231" + encode_address(address2)), + ) + + assert int.from_bytes(balance, "big") == 10000 diff --git a/src/empty_db_wrapper.rs b/src/empty_db_wrapper.rs index 7f43dd1..de7a235 100644 --- a/src/empty_db_wrapper.rs +++ b/src/empty_db_wrapper.rs @@ -1,13 +1,12 @@ use std::convert::Infallible; use revm::{ - Database, db::{DatabaseRef, EmptyDB}, primitives::{AccountInfo, Bytecode}, }; use revm::primitives::{Address, B256, U256}; /// An empty database that always returns default values when queried. -/// This will also _always_ return `Some(AccountInfo)`: +/// This will also _always_ return `Some(AccountInfo)`. /// Copied from Foundry: https://github.com/foundry-rs/foundry/blob/9e3ab9b3aff21c6e5ef/crates/evm/core/src/backend/in_memory_db.rs#L83-L92 #[derive(Clone, Debug, Default)] @@ -32,4 +31,3 @@ impl DatabaseRef for EmptyDBWrapper { Ok(self.0.block_hash_ref(number)?) } } - diff --git a/src/evm.rs b/src/evm.rs index 8223fef..76670fd 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,64 +1,86 @@ use std::collections::HashMap; use std::fmt::Debug; +use std::sync::Arc; +use ethers_core::types::BlockId; +use std::str::FromStr; -use pyo3::exceptions::PyRuntimeError; use pyo3::prelude::*; -use revm::{Database, DatabaseCommit, DatabaseRef, Evm, InMemoryDB, primitives::U256}; -use revm::db::CacheDB; +use revm::{Database, DatabaseCommit, DatabaseRef, Evm, primitives::U256}; +use revm::db::{CacheDB, EthersDB}; use revm::precompile::{Address, Bytes}; use revm::precompile::B256; -use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, AccountInfo as RevmAccountInfo, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::{AccountInfo as RevmAccountInfo, BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, ExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; use tracing::{trace, warn}; +use ethers_providers::{Http, Provider}; -use crate::{ - types::{AccountInfo, Env}, - utils::addr, -}; +use crate::{types::{AccountInfo, Env}, utils, utils::addr}; use crate::empty_db_wrapper::EmptyDBWrapper; +use crate::utils::pydict; + +type MemDB = CacheDB; +type ForkDB = CacheDB>>; +#[derive(Clone, Debug)] +pub enum DB<'a> { + Memory(&'a MemDB), + Fork(&'a ForkDB), +} -type DB = CacheDB; #[derive(Clone, Debug)] #[pyclass] pub struct EVM { - /// The underlying `revm::Database` that contains the EVM storage. - // Note: We do not store an EVM here, since we are really - // only interested in the database. REVM's `EVM` is a thin - // wrapper around spawning a new EVM on every call anyway, - // so the performance difference should be negligible. - pub db: DB, + /// The underlying `Database` that contains the EVM storage. + pub db: MemDB, /// The EVM environment. pub env: RevmEnv, + /// the current handler configuration pub handler_cfg: HandlerCfg, /// The gas limit for calls and deployments. This is different from the gas limit imposed by /// the passed in environment, as those limits are used by the EVM for certain opcodes like /// `gaslimit`. gas_limit: U256, + + /// The fork to use for the EVM. If `None`, the EVM will use the memory database. + fork: Option, } impl EVM { - pub fn db(&self) -> &DB { - &self.db + pub fn db(&self) -> DB<'_> { + if let Some(fork) = &self.fork { + DB::Fork(&fork) + } else { + DB::Memory(&self.db) + } } } -fn pyerr(err: T) -> PyErr { - PyRuntimeError::new_err(format!("{:?}", err)) -} - #[pymethods] impl EVM { + /// Create a new EVM instance. #[new] - #[pyo3(signature = (env=None, gas_limit=18446744073709551615, tracing=false, spec_id="SHANGHAI"))] + #[pyo3(signature = (env=None, fork_url=None, fork_block_number=None, gas_limit=18446744073709551615, tracing=false, spec_id="SHANGHAI"))] fn new( env: Option, + fork_url: Option<&str>, + fork_block_number: Option<&str>, gas_limit: u64, tracing: bool, spec_id: &str, ) -> PyResult { + let fork_option: Option> = fork_url.map( + |url| { + let p = Provider::::try_from(url).map_err(utils::pyerr)?; + let client = Arc::new(p); + let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(utils::pyerr)?; + let db = EthersDB::new(client, block).unwrap(); + Ok(CacheDB::new(db)) + } + ); + Ok(EVM { - db: DB::default(), + fork: fork_option.map_or(Ok(None), |v| v.map(Some)).map_err(utils::pyerr)?, + db: MemDB::default(), env: env.unwrap_or_default().into(), gas_limit: U256::from(gas_limit), handler_cfg: HandlerCfg::new(SpecId::from(spec_id)), @@ -67,34 +89,25 @@ impl EVM { /// Get basic account information. fn basic(&mut self, address: &str) -> PyResult { - let db_account = self.db.basic_ref(addr(address)?).map_err(pyerr)?; + let db_account = self.db.basic_ref(addr(address)?).map_err(utils::pyerr)?; Ok(db_account.unwrap_or_default().into()) } - fn get_accounts(&self) -> PyResult> { - // self.db - // .journaled_state - // .load_account(tx_caller, &mut context.evm.inner.db)?; - Ok(self.db.accounts.iter().map( - |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) - ).collect()) - } - /// Get account code by its hash. #[pyo3(signature = (code_hash))] fn code_by_hash(&mut self, code_hash: &str) -> PyResult> { - let hash = code_hash.parse::().map_err(pyerr)?; - Ok(self.db.code_by_hash(hash).map(|c| c.bytecode.to_vec()).map_err(pyerr)?) + let hash = code_hash.parse::().map_err(utils::pyerr)?; + Ok(self.db.code_by_hash(hash).map(|c| c.bytecode.to_vec()).map_err(utils::pyerr)?) } /// Get storage value of address at index. fn storage(&mut self, address: &str, index: U256) -> PyResult { - Ok(self.db.storage(addr(address)?, index).map_err(pyerr)?) + Ok(self.db.storage(addr(address)?, index).map_err(utils::pyerr)?) } /// Get block hash by block number. fn block_hash(&mut self, number: U256) -> PyResult> { - Ok(self.db.block_hash(number).map(|h| h.to_vec()).map_err(pyerr)?) + Ok(self.db.block_hash(number).map(|h| h.to_vec()).map_err(utils::pyerr)?) } /// Inserts the provided account information in the database at the specified address. @@ -112,10 +125,10 @@ impl EVM { /// Set the balance of a given address. fn set_balance(&mut self, address: &str, balance: U256) -> PyResult<()> { let target = addr(address)?; - let mut info = self.db.basic(target).map_err(pyerr)?.unwrap_or_default(); + let mut info = self.db.basic(target).map_err(utils::pyerr)?.unwrap_or_default(); info.balance = balance; self.db.insert_account_info(target, info.clone()); - assert_eq!(self.db.load_account(target).map(|a| a.info.clone()).map_err(pyerr)?, info); + assert_eq!(self.db.load_account(target).map(|a| a.info.clone()).map_err(utils::pyerr)?, info); // assert_eq!(self.db.basic(target).map(|a| a.unwrap_or_default().balance).map_err(pyerr)?, balance); Ok(()) } @@ -123,13 +136,13 @@ impl EVM { /// Retrieve the balance of a given address. fn get_balance(&mut self, address: &str) -> PyResult { // Ok(self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) - let acc = self.db.load_account(addr(address)?).map_err(pyerr)?; + let acc = self.db.load_account(addr(address)?).map_err(utils::pyerr)?; // let db_account = self.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); // assert_eq!(db_account.balance, acc.info.balance); Ok(acc.info.balance) } - // runs a raw call and returns the result + /// runs a raw call and returns the result #[pyo3(signature = (caller, to, calldata=None, value=None))] pub fn call_raw_committing( &mut self, @@ -155,11 +168,11 @@ impl EVM { to: &str, calldata: Option>, value: Option, - ) -> PyResult> { + ) -> PyResult<(Vec, HashMap)> { match call_raw(self, caller, to, calldata, value) { // todo: return state to the caller - Ok((data, state)) => Ok(data.to_vec()), + Ok((data, state)) => Ok((data.to_vec(), pydict(state))), Err(e) => Err(e), } } @@ -173,7 +186,7 @@ impl EVM { _abi: Option<&str>, ) -> PyResult { let env = build_test_env(self, addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); - match deploy_with_env(&self.db, env) + match deploy_with_env(self.db(), env) { Ok((address, state)) => { self.db.commit(state); @@ -225,7 +238,7 @@ fn build_test_env( /// Deploys a contract using the given `env` and commits the new state to the underlying /// database fn deploy_with_env( - db: &DB, + db: DB<'_>, env: EnvWithHandlerCfg, ) -> PyResult<(Address, State)> { debug_assert!( @@ -234,14 +247,7 @@ fn deploy_with_env( ); trace!(sender=?env.tx.caller, "deploying contract"); - let ResultAndState { - result, state - } = Evm::builder() - .with_ref_db(db) - .with_env_with_handler_cfg(env) - .build() - .transact() - .map_err(pyerr)?; + let (result, state) = execute(db, env)?; match &result { Success { reason, gas_used, gas_refunded, logs, output } => { @@ -250,16 +256,37 @@ fn deploy_with_env( Output::Create(_, address) => { Ok((address.unwrap(), state)) } - _ => Err(pyerr("Invalid output")), + _ => Err(utils::pyerr("Invalid output")), } }, - _ => Err(pyerr(result.clone())), + _ => Err(utils::pyerr(result.clone())), } } +fn execute(db: DB<'_>, env: EnvWithHandlerCfg) -> Result<(ExecutionResult, State), PyErr> { + let ResultAndState { + result, state + } = match db { + DB::Memory(db) => + Evm::builder() + .with_ref_db(db) + .with_env_with_handler_cfg(env) + .build() + .transact() + .map_err(utils::pyerr)?, + DB::Fork(db) => Evm::builder() + .with_ref_db(db) + .with_env_with_handler_cfg(env) + .build() + .transact() + .map_err(utils::pyerr)?, + }; + Ok((result, state)) +} + fn call_raw_with_env( - db: &DB, + db: DB<'_>, env: EnvWithHandlerCfg, ) -> PyResult<(Bytes, State)> { debug_assert!( @@ -268,16 +295,7 @@ fn call_raw_with_env( ); trace!(sender=?env.tx.caller, "deploying contract"); - let transaction = Evm::builder() - .with_ref_db(&db) - .with_env_with_handler_cfg(env) - .build() - .transact() - .map_err(pyerr)?; - - let ResultAndState { - result, state - } = transaction; + let (result, state) = execute(db, env)?; match &result { Success { reason, gas_used, gas_refunded, logs, output } => { @@ -286,7 +304,7 @@ fn call_raw_with_env( Ok((data, state)) }, // todo: state might have changed even if the call failed - _ => Err(pyerr(result.clone())), + _ => Err(utils::pyerr(result.clone())), } } @@ -298,5 +316,5 @@ fn call_raw( value: Option, ) -> PyResult<(Bytes, State)> { let env = build_test_env(&evm, addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - call_raw_with_env(&evm.db, env) + call_raw_with_env(evm.db(), env) } diff --git a/src/utils.rs b/src/utils.rs index a91c4de..0e08171 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,9 @@ use pyo3::{exceptions::PyTypeError, prelude::*}; -use revm::primitives::Address; +use revm::primitives::{Address, State}; +use std::fmt::Debug; +use pyo3::exceptions::PyRuntimeError; +use std::collections::HashMap; +use crate::AccountInfo; pub(crate) fn addr(s: &str) -> Result { s.parse::
() @@ -12,3 +16,14 @@ pub(crate) fn addr_or_zero(s: Option<&str>) -> Result { None => Ok(Address::ZERO), } } + +pub(crate) fn pydict(res: State) -> HashMap { + res.iter().map( + |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) + ).collect() +} + +/// Convert a Rust error into a Python error. +pub fn pyerr(err: T) -> PyErr { + PyRuntimeError::new_err(format!("{:?}", err)) +} From 64e9459bed5384c905f9800ec2e45427aea22499 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Mon, 18 Mar 2024 14:09:45 +0100 Subject: [PATCH 06/33] Cleanup --- src/evm.rs | 20 ++++++-------------- src/utils.rs | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/evm.rs b/src/evm.rs index 76670fd..0ee10d5 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -16,7 +16,7 @@ use ethers_providers::{Http, Provider}; use crate::{types::{AccountInfo, Env}, utils, utils::addr}; use crate::empty_db_wrapper::EmptyDBWrapper; -use crate::utils::pydict; +use crate::utils::{pydict, pyerr}; type MemDB = CacheDB; type ForkDB = CacheDB>>; @@ -116,9 +116,7 @@ impl EVM { address: &str, info: AccountInfo, ) -> PyResult<()> { - let info = RevmAccountInfo::from(info); - self.db.insert_account_info(addr(address)?, info.clone()); - assert_eq!(self.db.basic(addr(address)?).unwrap().unwrap().balance, info.balance); + self.db.insert_account_info(addr(address)?, info.clone().into()); Ok(()) } @@ -128,18 +126,13 @@ impl EVM { let mut info = self.db.basic(target).map_err(utils::pyerr)?.unwrap_or_default(); info.balance = balance; self.db.insert_account_info(target, info.clone()); - assert_eq!(self.db.load_account(target).map(|a| a.info.clone()).map_err(utils::pyerr)?, info); - // assert_eq!(self.db.basic(target).map(|a| a.unwrap_or_default().balance).map_err(pyerr)?, balance); Ok(()) } /// Retrieve the balance of a given address. fn get_balance(&mut self, address: &str) -> PyResult { - // Ok(self.db.basic(addr(address).map_err(pyerr)?)?.map(|acc| acc.balance)) - let acc = self.db.load_account(addr(address)?).map_err(utils::pyerr)?; - // let db_account = self.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); - // assert_eq!(db_account.balance, acc.info.balance); - Ok(acc.info.balance) + let RevmAccountInfo { balance, .. } = self.db.basic(addr(address)?).map_err(utils::pyerr)?.unwrap_or_default(); + Ok(balance) } /// runs a raw call and returns the result @@ -171,7 +164,6 @@ impl EVM { ) -> PyResult<(Vec, HashMap)> { match call_raw(self, caller, to, calldata, value) { - // todo: return state to the caller Ok((data, state)) => Ok((data.to_vec(), pydict(state))), Err(e) => Err(e), } @@ -256,10 +248,10 @@ fn deploy_with_env( Output::Create(_, address) => { Ok((address.unwrap(), state)) } - _ => Err(utils::pyerr("Invalid output")), + _ => Err(pyerr("Invalid output")), } }, - _ => Err(utils::pyerr(result.clone())), + _ => Err(pyerr(result.clone())), } } diff --git a/src/utils.rs b/src/utils.rs index 0e08171..fe5a4de 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -24,6 +24,6 @@ pub(crate) fn pydict(res: State) -> HashMap { } /// Convert a Rust error into a Python error. -pub fn pyerr(err: T) -> PyErr { +pub(crate) fn pyerr(err: T) -> PyErr { PyRuntimeError::new_err(format!("{:?}", err)) } From 1a8d390ddc885de901b69bbf62b9a55baeffac10 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Tue, 19 Mar 2024 10:09:08 +0100 Subject: [PATCH 07/33] Extract database implementation into separate class pyo3 will not accept lifetime/generic parameters so a lot of boilerplate code is needed. --- pyrevm.pyi | 93 ++++++++++---- pytest/test.py | 36 ++++-- src/database.rs | 120 ++++++++++++++++++ src/evm.rs | 282 +++++++++++++++++-------------------------- src/lib.rs | 8 +- src/types/evm_env.rs | 88 +++++++++++++- src/types/mod.rs | 3 - src/types/opts.rs | 24 ---- 8 files changed, 416 insertions(+), 238 deletions(-) create mode 100644 src/database.rs delete mode 100644 src/types/opts.rs diff --git a/pyrevm.pyi b/pyrevm.pyi index 386d6e4..88a7d14 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -16,6 +16,21 @@ class BlockEnv: gas_limit: Optional[int] = None, ) -> "BlockEnv": ... + @property + def number(self) -> Optional[int]: ... + @property + def coinbase(self) -> Optional[str]: ... + @property + def timestamp(self) -> Optional[int]: ... + @property + def difficulty(self) -> Optional[int]: ... + @property + def prevrandao(self) -> Optional[bytes]: ... + @property + def basefee(self) -> Optional[int]: ... + @property + def gas_limit(self) -> Optional[int]: ... + class TxEnv: def __new__( cls: Type["TxEnv"], @@ -30,6 +45,25 @@ class TxEnv: nonce: Optional[int] = None, ) -> "TxEnv": ... + @property + def caller(self) -> Optional[str]: ... + @property + def gas_limit(self) -> Optional[int]: ... + @property + def gas_price(self) -> Optional[int]: ... + @property + def gas_priority_fee(self) -> Optional[int]: ... + @property + def to(self) -> Optional[str]: ... + @property + def value(self) -> Optional[int]: ... + @property + def data(self) -> Optional[bytes]: ... + @property + def chain_id(self) -> Optional[int]: ... + @property + def nonce(self) -> Optional[int]: ... + class Env: def __new__( cls: Type["Env"], @@ -37,16 +71,14 @@ class Env: block: Optional[BlockEnv] = None, tx: Optional[TxEnv] = None, ) -> "Env": ... - -class AccountInfo: - @property - def balance(self: "AccountInfo") -> int: ... @property - def nonce(self: "AccountInfo") -> int: ... + def cfg(self: "AccountInfo") -> Optional[CfgEnv]: ... @property - def code(self: "AccountInfo") -> bytes: ... + def block(self: "AccountInfo") -> Optional[BlockEnv]: ... @property - def code_hash(self: "AccountInfo") -> bytes: ... + def tx(self: "AccountInfo") -> Optional[TxEnv]: ... + +class AccountInfo: def __new__( cls: Type["AccountInfo"], nonce: int = 0, @@ -54,24 +86,21 @@ class AccountInfo: code: Optional[bytes] = None, ) -> "AccountInfo": ... -class EvmOpts: - env: Env - fork_url: Optional[str] - fork_block_number: Optional[int] - gas_limit: int - tracing: bool - def __new__( - cls: Type["EvmOpts"], - env: Optional[Env], - fork_url: Optional[str], - ) -> "EvmOpts": ... + @property + def balance(self: "AccountInfo") -> int: ... + @property + def nonce(self: "AccountInfo") -> int: ... + @property + def code(self: "AccountInfo") -> bytes: ... + @property + def code_hash(self: "AccountInfo") -> bytes: ... class EVM: def __new__( cls: Type["EVM"], env: Optional[Env] = None, fork_url: Optional[str] = None, - fork_block_number: Optional[int] = None, + fork_block_number: Optional[str] = None, gas_limit: int = 2**64 - 1, tracing: bool = False, spec_id="SHANGHAI", @@ -109,7 +138,7 @@ class EVM: Processes a raw call, committing the result to the state. :param caller: The address of the caller. :param to: The address of the callee. - :param calldata: The calldata. + :param calldata: The data to pass to the contract. :param value: The value. :return: The return data. """ @@ -135,7 +164,15 @@ class EVM: deployer: str, code: bytes, value: Optional[int] = None, - ) -> str: ... + ) -> str: + """ + Deploys the given code. + :param deployer: The address of the deployer. + :param code: The code. + :param value: The value. + :return: The address of the deployed contract. + """ + def get_balance(self: "EVM", address: str) -> int: """ Returns the balance of the given address. @@ -143,9 +180,21 @@ class EVM: :return: The balance. """ - def set_balance(self: "EVM", address: str, balance: int) -> None + def set_balance(self: "EVM", address: str, balance: int) -> None: """ Sets the balance of the given address. :param address: The address. :param balance: The balance. """ + + def storage(self: "EVM", address: str, index: int) -> int: + """ + Returns the storage value of the given address at the given index. + :param address: The address. + :param index: The index. + :return: The storage value. + """ + + @property + def env(self: "EVM") -> Env: + """ Get the environment. """ diff --git a/pytest/test.py b/pytest/test.py index 4d84e9e..50fb96d 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -8,6 +8,12 @@ fork_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27" +KWARG_OPTS = [ + {"fork_url": fork_url, "tracing": True}, + {"fork_url": fork_url, "tracing": False, "fork_block_number": "latest"}, + {}, +] + def load_contract_bin(contract_name: str) -> bytes: with open( @@ -26,7 +32,7 @@ def encode_address(address: str) -> str: return f'{"0" * 24}{address[2:]}' -def test_revm(): +def test_revm_fork(): # set up an evm evm = EVM( # can fork from a remote node @@ -86,8 +92,22 @@ def test_balances(): assert evm.basic(address).balance == AMT -def test_call_raw(): - evm = EVM() +def test_balances_fork(): + evm = EVM(fork_url=fork_url, fork_block_number="0x3b01f793ed1923cd82df5fe345b3e12211aedd514c8546e69efd6386dc0c9a97") + + vb_before = evm.basic(address) + assert vb_before.balance == 955628344913799071315 + + AMT = 10000 + evm.set_balance(address, AMT) + + assert evm.get_balance(address) == AMT + assert evm.basic(address).balance == AMT + + +@pytest.mark.parametrize("kwargs", KWARG_OPTS) +def test_call_raw(kwargs): + evm = EVM(**kwargs) info = AccountInfo(code=load_contract_bin("full_math.bin")) evm.insert_account_info(address, info) assert evm.basic(address).code == info.code @@ -106,8 +126,9 @@ def test_call_raw(): assert changes[address2].nonce == 1 -def test_call_committing(): - evm = EVM() +@pytest.mark.parametrize("kwargs", KWARG_OPTS) +def test_call_committing(kwargs): + evm = EVM(**kwargs) evm.insert_account_info( address, AccountInfo(code=load_contract_bin("full_math.bin")) ) @@ -124,8 +145,9 @@ def test_call_committing(): assert int.from_bytes(result, "big") == 171 -def test_call_empty_result(): - evm = EVM() +@pytest.mark.parametrize("kwargs", KWARG_OPTS) +def test_call_empty_result(kwargs): + evm = EVM(**kwargs) evm.insert_account_info(address, AccountInfo(code=load_contract_bin("weth_9.bin"))) evm.set_balance(address2, 10000) diff --git a/src/database.rs b/src/database.rs new file mode 100644 index 0000000..e710296 --- /dev/null +++ b/src/database.rs @@ -0,0 +1,120 @@ +use std::str::FromStr; +use std::sync::Arc; + +use ethers_core::types::BlockId; +use ethers_providers::{Http, Provider}; +use pyo3::{PyErr, PyResult}; +use revm::Database; +use revm::db::{CacheDB, EthersDB}; +use revm::precompile::{Address, B256}; +use revm::primitives::{AccountInfo, Bytecode, State}; +use revm_interpreter::primitives::db::{DatabaseCommit, DatabaseRef}; +use ruint::aliases::U256; + +use crate::empty_db_wrapper::EmptyDBWrapper; +use crate::utils::pyerr; + +type MemDB = CacheDB; +type ForkDB = CacheDB>>; +#[derive(Clone, Debug)] +pub enum DB { + Memory(Box), + Fork(Box), +} + +impl DB { + pub fn new_memory() -> Self { + DB::Memory(Box::new(MemDB::new(EmptyDBWrapper::default()))) + } + + pub fn new_fork( + fork_url: &str, + fork_block_number: Option<&str>, + ) -> PyResult { + let client = Arc::new(Provider::::try_from(fork_url).map_err(pyerr)?); + let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; + let db = EthersDB::new(client, block).unwrap(); + Ok(DB::Fork(Box::new(CacheDB::new(db)))) + } + + /// Insert account info but not override storage + pub fn insert_account_info(&mut self, address: Address, info: AccountInfo) { + match self { + DB::Memory(db) => db.insert_account_info(address, info), + DB::Fork(db) => db.insert_account_info(address, info), + } + } +} + +impl Database for DB { + type Error = PyErr; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + Ok(match self { + DB::Memory(db) => db.basic(address).map_err(pyerr)?, + DB::Fork(db) => db.basic(address).map_err(pyerr)?, + }) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + Ok(match self { + DB::Memory(db) => db.code_by_hash(code_hash).map_err(pyerr)?, + DB::Fork(db) => db.code_by_hash(code_hash).map_err(pyerr)?, + }) + } + + fn storage(&mut self, address: Address, index: U256) -> Result { + Ok(match self { + DB::Memory(db) => db.storage(address, index).map_err(pyerr)?, + DB::Fork(db) => db.storage(address, index).map_err(pyerr)?, + }) + } + + fn block_hash(&mut self, number: U256) -> Result { + Ok(match self { + DB::Memory(db) => db.block_hash(number).map_err(pyerr)?, + DB::Fork(db) => db.block_hash(number).map_err(pyerr)?, + }) + } +} + +impl DatabaseCommit for DB { + fn commit(&mut self, changes: State) { + match self { + DB::Memory(ref mut db) => db.commit(changes), + DB::Fork(ref mut db) => db.commit(changes), + } + } +} + +impl DatabaseRef for DB { + type Error = PyErr; + + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + Ok(match self { + DB::Memory(db) => db.basic_ref(address).map_err(pyerr)?, + DB::Fork(db) => db.basic_ref(address).map_err(pyerr)?, + }) + } + + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + Ok(match self { + DB::Memory(db) => db.code_by_hash_ref(code_hash).map_err(pyerr)?, + DB::Fork(db) => db.code_by_hash_ref(code_hash).map_err(pyerr)?, + }) + } + + fn storage_ref(&self, address: Address, index: U256) -> Result { + Ok(match self { + DB::Memory(db) => db.storage_ref(address, index).map_err(pyerr)?, + DB::Fork(db) => db.storage_ref(address, index).map_err(pyerr)?, + }) + } + + fn block_hash_ref(&self, number: U256) -> Result { + Ok(match self { + DB::Memory(db) => db.block_hash_ref(number).map_err(pyerr)?, + DB::Fork(db) => db.block_hash_ref(number).map_err(pyerr)?, + }) + } +} diff --git a/src/evm.rs b/src/evm.rs index 0ee10d5..aa3337d 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,37 +1,24 @@ use std::collections::HashMap; use std::fmt::Debug; -use std::sync::Arc; -use ethers_core::types::BlockId; -use std::str::FromStr; +use pyo3::{PyErr, pymethods, PyResult, pyclass}; -use pyo3::prelude::*; -use revm::{Database, DatabaseCommit, DatabaseRef, Evm, primitives::U256}; -use revm::db::{CacheDB, EthersDB}; +use revm::{Database, Evm, primitives::U256}; +use revm::DatabaseCommit; use revm::precompile::{Address, Bytes}; use revm::precompile::B256; -use revm::primitives::{AccountInfo as RevmAccountInfo, BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, ExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::{AccountInfo as RevmAccountInfo, BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; use tracing::{trace, warn}; -use ethers_providers::{Http, Provider}; -use crate::{types::{AccountInfo, Env}, utils, utils::addr}; -use crate::empty_db_wrapper::EmptyDBWrapper; -use crate::utils::{pydict, pyerr}; - -type MemDB = CacheDB; -type ForkDB = CacheDB>>; -#[derive(Clone, Debug)] -pub enum DB<'a> { - Memory(&'a MemDB), - Fork(&'a ForkDB), -} +use crate::{types::{AccountInfo, Env}, utils::{addr, pydict, pyerr}}; +use crate::database::DB; #[derive(Clone, Debug)] #[pyclass] pub struct EVM { /// The underlying `Database` that contains the EVM storage. - pub db: MemDB, + pub db: DB, /// The EVM environment. pub env: RevmEnv, /// the current handler configuration @@ -40,19 +27,6 @@ pub struct EVM { /// the passed in environment, as those limits are used by the EVM for certain opcodes like /// `gaslimit`. gas_limit: U256, - - /// The fork to use for the EVM. If `None`, the EVM will use the memory database. - fork: Option, -} - -impl EVM { - pub fn db(&self) -> DB<'_> { - if let Some(fork) = &self.fork { - DB::Fork(&fork) - } else { - DB::Memory(&self.db) - } - } } #[pymethods] @@ -68,46 +42,34 @@ impl EVM { tracing: bool, spec_id: &str, ) -> PyResult { - let fork_option: Option> = fork_url.map( - |url| { - let p = Provider::::try_from(url).map_err(utils::pyerr)?; - let client = Arc::new(p); - let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(utils::pyerr)?; - let db = EthersDB::new(client, block).unwrap(); - Ok(CacheDB::new(db)) - } - ); - Ok(EVM { - fork: fork_option.map_or(Ok(None), |v| v.map(Some)).map_err(utils::pyerr)?, - db: MemDB::default(), + db: fork_url.map(|url| DB::new_fork(url, fork_block_number)).unwrap_or(Ok(DB::new_memory()))?, env: env.unwrap_or_default().into(), gas_limit: U256::from(gas_limit), - handler_cfg: HandlerCfg::new(SpecId::from(spec_id)), + handler_cfg: HandlerCfg::new(SpecId::from(spec_id)) }) } /// Get basic account information. fn basic(&mut self, address: &str) -> PyResult { - let db_account = self.db.basic_ref(addr(address)?).map_err(utils::pyerr)?; - Ok(db_account.unwrap_or_default().into()) + Ok(self.db.basic(addr(address)?)?.unwrap_or_default().into()) } /// Get account code by its hash. #[pyo3(signature = (code_hash))] fn code_by_hash(&mut self, code_hash: &str) -> PyResult> { - let hash = code_hash.parse::().map_err(utils::pyerr)?; - Ok(self.db.code_by_hash(hash).map(|c| c.bytecode.to_vec()).map_err(utils::pyerr)?) + let hash = code_hash.parse::().map_err(pyerr)?; + Ok(self.db.code_by_hash(hash)?.bytecode.to_vec()) } /// Get storage value of address at index. fn storage(&mut self, address: &str, index: U256) -> PyResult { - Ok(self.db.storage(addr(address)?, index).map_err(utils::pyerr)?) + Ok(self.db.storage(addr(address)?, index)?) } /// Get block hash by block number. fn block_hash(&mut self, number: U256) -> PyResult> { - Ok(self.db.block_hash(number).map(|h| h.to_vec()).map_err(utils::pyerr)?) + Ok(self.db.block_hash(number)?.to_vec()) } /// Inserts the provided account information in the database at the specified address. @@ -122,16 +84,15 @@ impl EVM { /// Set the balance of a given address. fn set_balance(&mut self, address: &str, balance: U256) -> PyResult<()> { - let target = addr(address)?; - let mut info = self.db.basic(target).map_err(utils::pyerr)?.unwrap_or_default(); + let mut info = self.db.basic(addr(address)?)?.unwrap_or_default(); info.balance = balance; - self.db.insert_account_info(target, info.clone()); + self.db.insert_account_info(addr(address)?, info); Ok(()) } /// Retrieve the balance of a given address. fn get_balance(&mut self, address: &str) -> PyResult { - let RevmAccountInfo { balance, .. } = self.db.basic(addr(address)?).map_err(utils::pyerr)?.unwrap_or_default(); + let RevmAccountInfo { balance, .. } = self.db.basic(addr(address)?)?.unwrap_or_default(); Ok(balance) } @@ -144,7 +105,8 @@ impl EVM { calldata: Option>, value: Option, ) -> PyResult> { - match call_raw(self, caller, to, calldata, value) + let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); + match self.call_raw_with_env(env) { Ok((data, state)) => { self.db.commit(state); @@ -162,7 +124,8 @@ impl EVM { calldata: Option>, value: Option, ) -> PyResult<(Vec, HashMap)> { - match call_raw(self, caller, to, calldata, value) + let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); + match self.call_raw_with_env(env) { Ok((data, state)) => Ok((data.to_vec(), pydict(state))), Err(e) => Err(e), @@ -177,8 +140,8 @@ impl EVM { value: Option, _abi: Option<&str>, ) -> PyResult { - let env = build_test_env(self, addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); - match deploy_with_env(self.db(), env) + let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); + match self.deploy_with_env(env) { Ok((address, state)) => { self.db.commit(state); @@ -188,125 +151,104 @@ impl EVM { } } + #[getter] + fn env(&self) -> PyResult { + Ok(self.env.clone().into()) + } } -/// Creates the environment to use when executing a transaction in a test context -/// -/// If using a backend with cheatcodes, `tx.gas_price` and `block.number` will be overwritten by -/// the cheatcode state inbetween calls. -fn build_test_env( - evm: &EVM, - caller: Address, - transact_to: TransactTo, - data: Bytes, - value: U256, -) -> EnvWithHandlerCfg { - let env = revm::primitives::Env { - cfg: evm.env.cfg.clone(), - // We always set the gas price to 0, so we can execute the transaction regardless of - // network conditions - the actual gas price is kept in `evm.block` and is applied by - // the cheatcode handler if it is enabled - block: BlockEnv { - basefee: U256::ZERO, - gas_limit: evm.gas_limit, - ..evm.env.block.clone() - }, - tx: TxEnv { - caller, - transact_to, - data, - value, - // As above, we set the gas price to 0. - gas_price: U256::ZERO, - gas_priority_fee: None, - gas_limit: evm.gas_limit.to(), - ..evm.env.tx.clone() - }, - }; +impl EVM { + /// Creates the environment to use when executing a transaction in a test context + /// + /// If using a backend with cheatcodes, `tx.gas_price` and `block.number` will be overwritten by + /// the cheatcode state inbetween calls. + fn build_test_env( + &self, + caller: Address, + transact_to: TransactTo, + data: Bytes, + value: U256, + ) -> EnvWithHandlerCfg { + let env = revm::primitives::Env { + cfg: self.env.cfg.clone(), + // We always set the gas price to 0, so we can execute the transaction regardless of + // network conditions - the actual gas price is kept in `evm.block` and is applied by + // the cheatcode handler if it is enabled + block: BlockEnv { + basefee: U256::ZERO, + gas_limit: self.gas_limit, + ..self.env.block.clone() + }, + tx: TxEnv { + caller, + transact_to, + data, + value, + // As above, we set the gas price to 0. + gas_price: U256::ZERO, + gas_priority_fee: None, + gas_limit: self.gas_limit.to(), + ..self.env.tx.clone() + }, + }; - EnvWithHandlerCfg::new_with_spec_id(Box::new(env), evm.handler_cfg.spec_id) -} + EnvWithHandlerCfg::new_with_spec_id(Box::new(env), self.handler_cfg.spec_id) + } -/// Deploys a contract using the given `env` and commits the new state to the underlying -/// database -fn deploy_with_env( - db: DB<'_>, - env: EnvWithHandlerCfg, -) -> PyResult<(Address, State)> { - debug_assert!( - matches!(env.tx.transact_to, TransactTo::Create(_)), - "Expect create transaction" - ); - trace!(sender=?env.tx.caller, "deploying contract"); + /// Deploys a contract using the given `env` and commits the new state to the underlying + /// database + fn deploy_with_env(&self, env: EnvWithHandlerCfg) -> PyResult<(Address, State)> { + debug_assert!( + matches!(env.tx.transact_to, TransactTo::Create(_)), + "Expect create transaction" + ); + trace!(sender=?env.tx.caller, "deploying contract"); + + let ResultAndState { result, state } = self.run_env(env)?; + + match &result { + Success { reason, gas_used, gas_refunded, logs, output } => { + warn!(reason=?reason, gas_used, gas_refunded, "contract deployed"); + match output { + Output::Create(_, address) => { + Ok((address.unwrap(), state)) + } + _ => Err(pyerr("Invalid output")), + } + }, + _ => Err(pyerr(result.clone())), + } + } - let (result, state) = execute(db, env)?; + fn call_raw_with_env(&self, env: EnvWithHandlerCfg) -> PyResult<(Bytes, State)> + { + debug_assert!( + matches!(env.tx.transact_to, TransactTo::Call(_)), + "Expect call transaction" + ); + trace!(sender=?env.tx.caller, "deploying contract"); - match &result { - Success { reason, gas_used, gas_refunded, logs, output } => { - warn!(reason=?reason, gas_used, gas_refunded, "contract deployed"); - match output { - Output::Create(_, address) => { - Ok((address.unwrap(), state)) - } - _ => Err(pyerr("Invalid output")), - } - }, - _ => Err(pyerr(result.clone())), + let ResultAndState { result, state } = self.run_env(env)?; + + match &result { + Success { reason, gas_used, gas_refunded, logs, output } => { + let data = output.clone().into_data(); + trace!(reason=?reason, gas_used, gas_refunded, "call done"); + Ok((data, state)) + }, + // todo: state might have changed even if the call failed + _ => Err(pyerr(result.clone())), + } } -} -fn execute(db: DB<'_>, env: EnvWithHandlerCfg) -> Result<(ExecutionResult, State), PyErr> { - let ResultAndState { - result, state - } = match db { - DB::Memory(db) => - Evm::builder() - .with_ref_db(db) - .with_env_with_handler_cfg(env) - .build() - .transact() - .map_err(utils::pyerr)?, - DB::Fork(db) => Evm::builder() - .with_ref_db(db) + fn run_env(&self, env: EnvWithHandlerCfg) -> Result + { + let evm = Evm::builder() + .with_db(self.db.clone()) .with_env_with_handler_cfg(env) .build() .transact() - .map_err(utils::pyerr)?, - }; - Ok((result, state)) -} - - -fn call_raw_with_env( - db: DB<'_>, - env: EnvWithHandlerCfg, -) -> PyResult<(Bytes, State)> { - debug_assert!( - matches!(env.tx.transact_to, TransactTo::Call(_)), - "Expect call transaction" - ); - trace!(sender=?env.tx.caller, "deploying contract"); - - let (result, state) = execute(db, env)?; - - match &result { - Success { reason, gas_used, gas_refunded, logs, output } => { - let data = output.clone().into_data(); - trace!(reason=?reason, gas_used, gas_refunded, "call done"); - Ok((data, state)) - }, - // todo: state might have changed even if the call failed - _ => Err(utils::pyerr(result.clone())), + .map_err(pyerr)?; + Ok(evm) } -} - -fn call_raw( - evm: &EVM, - caller: &str, - to: &str, - calldata: Option>, - value: Option, -) -> PyResult<(Bytes, State)> { - let env = build_test_env(&evm, addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - call_raw_with_env(evm.db(), env) -} +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b90cb4b..9340204 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,12 +5,6 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![allow(clippy::too_many_arguments)] -// `pyo3` feature. -use ruint as _; - -// Pinning `revm`. -use revm_interpreter as _; - use pyo3::prelude::*; mod types; @@ -21,6 +15,7 @@ pub use evm::EVM; mod utils; mod empty_db_wrapper; +mod database; #[pymodule] fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { @@ -28,7 +23,6 @@ fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { // Types m.add_class::()?; - m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 4ba4a71..63c2813 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -1,9 +1,6 @@ use crate::utils::{addr, addr_or_zero}; -use pyo3::{exceptions::PyTypeError, prelude::*, types::PyBytes}; -use revm::primitives::{ - BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, CreateScheme, - Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256, -}; +use pyo3::{exceptions::PyTypeError, pyclass, pymethods, PyResult, types::PyBytes}; +use revm::primitives::{BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, CreateScheme, Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256}; #[pyclass] #[derive(Clone, Debug, Default)] @@ -20,6 +17,21 @@ impl Env { tx: tx.unwrap_or_default().into(), }) } + + #[getter] + fn cfg(&self) -> CfgEnv { + self.0.cfg.clone().into() + } + + #[getter] + fn block(&self) -> BlockEnv { + self.0.block.clone().into() + } + + #[getter] + fn tx(&self) -> TxEnv { + self.0.tx.clone().into() + } } impl From for Env { @@ -70,6 +82,54 @@ impl TxEnv { ..Default::default() })) } + + #[getter] + fn caller(&self) -> String { + self.0.caller.to_string() + } + + #[getter] + fn gas_limit(&self) -> u64 { + self.0.gas_limit + } + + #[getter] + fn gas_price(&self) -> U256 { + self.0.gas_price + } + + #[getter] + fn gas_priority_fee(&self) -> Option { + self.0.gas_priority_fee.map(Into::into) + } + + #[getter] + fn to(&self) -> Option { + match &self.0.transact_to { + TransactTo::Call(address) => Some(format!("{:?}", address)), + TransactTo::Create(_) => None, + } + } + + #[getter] + fn value(&self) -> U256 { + self.0.value + } + + #[getter] + fn data(&self) -> Vec { + self.0.data.to_vec() + } + + #[getter] + fn chain_id(&self) -> Option { + self.0.chain_id + } + + #[getter] + fn nonce(&self) -> Option { + self.0.nonce + } } impl From for RevmTxEnv { @@ -78,6 +138,12 @@ impl From for RevmTxEnv { } } +impl Into for RevmTxEnv { + fn into(self) -> TxEnv { + TxEnv(self) + } +} + #[pyclass] #[derive(Clone, Debug, Default)] pub struct BlockEnv(RevmBlockEnv); @@ -156,6 +222,12 @@ impl From for RevmBlockEnv { } } +impl Into for RevmBlockEnv { + fn into(self) -> BlockEnv { + BlockEnv(self) + } +} + #[pyclass] #[derive(Default, Clone, Debug)] pub struct CfgEnv(RevmCfgEnv); @@ -177,3 +249,9 @@ impl From for RevmCfgEnv { env.0 } } + +impl Into for RevmCfgEnv { + fn into(self) -> CfgEnv { + CfgEnv(self) + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 15921d0..0a905c0 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,8 +1,5 @@ mod evm_env; pub use evm_env::*; -mod opts; -pub use opts::EvmOpts; - mod info; pub use info::AccountInfo; diff --git a/src/types/opts.rs b/src/types/opts.rs deleted file mode 100644 index d0df934..0000000 --- a/src/types/opts.rs +++ /dev/null @@ -1,24 +0,0 @@ -use super::Env; -use pyo3::prelude::*; - -#[pyclass] -#[derive(Clone, Debug, Default)] -pub struct EvmOpts { - pub env: Env, - pub fork_url: Option, - pub fork_block_number: Option, - pub gas_limit: u64, - pub tracing: bool, -} - -#[pymethods] -impl EvmOpts { - #[new] - fn new(env: Option, fork_url: Option) -> Self { - Self { - env: env.unwrap_or_default(), - fork_url, - ..Default::default() - } - } -} From 7454bb00eab5e90f63743c1db111071bc92801b3 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Tue, 19 Mar 2024 14:37:54 +0100 Subject: [PATCH 08/33] Add tracing --- Cargo.toml | 2 +- pyrevm.pyi | 4 ++++ pytest/test.py | 32 ++++++++++++++++++++++----- src/evm.rs | 59 +++++++++++++++++++++++++++++++++++-------------- src/lib.rs | 1 + src/pystdout.rs | 25 +++++++++++++++++++++ 6 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 src/pystdout.rs diff --git a/Cargo.toml b/Cargo.toml index 9cad66b..735ef22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -revm = { "version"="7.1.0", features=["ethersdb", "serde"] } +revm = { "version"="7.1.0", features=["ethersdb", "serde", "serde-json", "std"] } revm-interpreter = "3.3.0" tracing = "0.1" pyo3 = { version = "0.19", features = ["extension-module"] } diff --git a/pyrevm.pyi b/pyrevm.pyi index 88a7d14..6662be0 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -198,3 +198,7 @@ class EVM: @property def env(self: "EVM") -> Env: """ Get the environment. """ + + @property + def tracing(self: "EVM") -> bool: + """ Whether tracing is enabled. """ diff --git a/pytest/test.py b/pytest/test.py index 50fb96d..55a88e6 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -1,3 +1,4 @@ +import json import os.path import pytest @@ -8,8 +9,8 @@ fork_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27" -KWARG_OPTS = [ - {"fork_url": fork_url, "tracing": True}, +KWARG_CASES = [ + {"fork_url": fork_url}, {"fork_url": fork_url, "tracing": False, "fork_block_number": "latest"}, {}, ] @@ -105,7 +106,7 @@ def test_balances_fork(): assert evm.basic(address).balance == AMT -@pytest.mark.parametrize("kwargs", KWARG_OPTS) +@pytest.mark.parametrize("kwargs", KWARG_CASES) def test_call_raw(kwargs): evm = EVM(**kwargs) info = AccountInfo(code=load_contract_bin("full_math.bin")) @@ -126,7 +127,7 @@ def test_call_raw(kwargs): assert changes[address2].nonce == 1 -@pytest.mark.parametrize("kwargs", KWARG_OPTS) +@pytest.mark.parametrize("kwargs", KWARG_CASES) def test_call_committing(kwargs): evm = EVM(**kwargs) evm.insert_account_info( @@ -145,7 +146,7 @@ def test_call_committing(kwargs): assert int.from_bytes(result, "big") == 171 -@pytest.mark.parametrize("kwargs", KWARG_OPTS) +@pytest.mark.parametrize("kwargs", KWARG_CASES) def test_call_empty_result(kwargs): evm = EVM(**kwargs) evm.insert_account_info(address, AccountInfo(code=load_contract_bin("weth_9.bin"))) @@ -168,3 +169,24 @@ def test_call_empty_result(kwargs): ) assert int.from_bytes(balance, "big") == 10000 + assert not evm.tracing + + +def test_tracing(capsys): + evm = EVM(tracing=True) + evm.insert_account_info(address, AccountInfo(code=load_contract_bin("weth_9.bin"))) + evm.set_balance(address2, 10000) + evm.call_raw_committing( + caller=address2, + to=address, + value=10000, + calldata=bytes.fromhex("d0e30db0"), + ) + assert evm.tracing + captured = capsys.readouterr() + traces = [json.loads(i) for i in captured.out.split("\n") if i] + assert {'gasUsed': '0xffffffffffff5011', + 'output': '0x', + 'pass': True, + 'stateRoot': '0x0000000000000000000000000000000000000000000000000000000000000000'} == traces[-1] + assert len(traces) == 128 diff --git a/src/evm.rs b/src/evm.rs index aa3337d..4d5e95d 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,17 +1,21 @@ use std::collections::HashMap; use std::fmt::Debug; +use std::io::stdout; use pyo3::{PyErr, pymethods, PyResult, pyclass}; +use pyo3::ffi::PySys_WriteStdout; -use revm::{Database, Evm, primitives::U256}; +use revm::{Database, Evm, inspector_handle_register, primitives::U256}; use revm::DatabaseCommit; use revm::precompile::{Address, Bytes}; use revm::precompile::B256; use revm::primitives::{AccountInfo as RevmAccountInfo, BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; +use revm::inspectors::TracerEip3155; use tracing::{trace, warn}; use crate::{types::{AccountInfo, Env}, utils::{addr, pydict, pyerr}}; use crate::database::DB; +use crate::pystdout::PySysStdout; #[derive(Clone, Debug)] @@ -27,6 +31,9 @@ pub struct EVM { /// the passed in environment, as those limits are used by the EVM for certain opcodes like /// `gaslimit`. gas_limit: U256, + + /// whether to trace the execution to stdout + tracing: bool, } #[pymethods] @@ -46,7 +53,8 @@ impl EVM { db: fork_url.map(|url| DB::new_fork(url, fork_block_number)).unwrap_or(Ok(DB::new_memory()))?, env: env.unwrap_or_default().into(), gas_limit: U256::from(gas_limit), - handler_cfg: HandlerCfg::new(SpecId::from(spec_id)) + handler_cfg: HandlerCfg::new(SpecId::from(spec_id)), + tracing, }) } @@ -118,7 +126,7 @@ impl EVM { #[pyo3(signature = (caller, to, calldata=None, value=None))] pub fn call_raw( - &self, + &mut self, caller: &str, to: &str, calldata: Option>, @@ -152,8 +160,13 @@ impl EVM { } #[getter] - fn env(&self) -> PyResult { - Ok(self.env.clone().into()) + fn env(&self) -> Env { + self.env.clone().into() + } + + #[getter] + fn tracing(&self) -> bool { + self.tracing } } @@ -197,7 +210,7 @@ impl EVM { /// Deploys a contract using the given `env` and commits the new state to the underlying /// database - fn deploy_with_env(&self, env: EnvWithHandlerCfg) -> PyResult<(Address, State)> { + fn deploy_with_env(&mut self, env: EnvWithHandlerCfg) -> PyResult<(Address, State)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Create(_)), "Expect create transaction" @@ -220,7 +233,7 @@ impl EVM { } } - fn call_raw_with_env(&self, env: EnvWithHandlerCfg) -> PyResult<(Bytes, State)> + fn call_raw_with_env(&mut self, env: EnvWithHandlerCfg) -> PyResult<(Bytes, State)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), @@ -241,14 +254,26 @@ impl EVM { } } - fn run_env(&self, env: EnvWithHandlerCfg) -> Result + fn run_env(&mut self, env: EnvWithHandlerCfg) -> Result { - let evm = Evm::builder() - .with_db(self.db.clone()) - .with_env_with_handler_cfg(env) - .build() - .transact() - .map_err(pyerr)?; - Ok(evm) - } -} \ No newline at end of file + let builder = Evm::builder() + .with_db(&mut self.db); + + let result = + if self.tracing { + let tracer = TracerEip3155::new(Box::new(PySysStdout {}), true); + builder + .with_external_context(tracer) + .with_env_with_handler_cfg(env) + .append_handler_register(inspector_handle_register) + .build() + .transact() + } else { + builder + .with_env_with_handler_cfg(env) + .build() + .transact() + }; + Ok(result.map_err(pyerr)?) + } +} diff --git a/src/lib.rs b/src/lib.rs index 9340204..2762b23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ pub use evm::EVM; mod utils; mod empty_db_wrapper; mod database; +mod pystdout; #[pymodule] fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { diff --git a/src/pystdout.rs b/src/pystdout.rs new file mode 100644 index 0000000..d4b579f --- /dev/null +++ b/src/pystdout.rs @@ -0,0 +1,25 @@ +use std::io::Write; +use pyo3::Python; +use pyo3::types::PyDict; + +pub(crate) struct PySysStdout; + +// alloow us to capture stdout from python +// based on https://github.com/PyO3/pyo3/discussions/1960#discussioncomment-8414724 +impl Write for PySysStdout { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let s = std::str::from_utf8(buf).unwrap(); + Python::with_gil(|py| { + let locals = PyDict::new(py); + locals.set_item("s", s).unwrap(); + py.run("print(s, end='')", None, Some(&locals)).unwrap(); + }); + Ok(buf.len()) + } + fn flush(&mut self) -> std::io::Result<()> { + Python::with_gil(|py| { + py.run("import sys;sys.stdout.flush()", None, None).unwrap(); + }); + Ok(()) + } +} From b05b48d4569a5e24d545eeac3662a529d8e60f62 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Tue, 19 Mar 2024 16:53:38 +0100 Subject: [PATCH 09/33] Add comments --- src/database.rs | 8 ++++++-- src/evm.rs | 16 +++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/database.rs b/src/database.rs index e710296..6c09cd4 100644 --- a/src/database.rs +++ b/src/database.rs @@ -16,6 +16,10 @@ use crate::utils::pyerr; type MemDB = CacheDB; type ForkDB = CacheDB>>; + + +/// A wrapper around the `CacheDB` and `EthersDB` to provide a common interface +/// without needing dynamic lifetime and generic parameters (unsupported in PyO3) #[derive(Clone, Debug)] pub enum DB { Memory(Box), @@ -31,9 +35,9 @@ impl DB { fork_url: &str, fork_block_number: Option<&str>, ) -> PyResult { - let client = Arc::new(Provider::::try_from(fork_url).map_err(pyerr)?); + let provider = Provider::::try_from(fork_url).map_err(pyerr)?; let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; - let db = EthersDB::new(client, block).unwrap(); + let db = EthersDB::new(Arc::new(provider), block).unwrap(); Ok(DB::Fork(Box::new(CacheDB::new(db)))) } diff --git a/src/evm.rs b/src/evm.rs index 4d5e95d..8da43fe 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -17,6 +17,8 @@ use crate::{types::{AccountInfo, Env}, utils::{addr, pydict, pyerr}}; use crate::database::DB; use crate::pystdout::PySysStdout; +// In Py03 we use vec to represent bytes +type PyBytes = Vec; #[derive(Clone, Debug)] #[pyclass] @@ -65,7 +67,7 @@ impl EVM { /// Get account code by its hash. #[pyo3(signature = (code_hash))] - fn code_by_hash(&mut self, code_hash: &str) -> PyResult> { + fn code_by_hash(&mut self, code_hash: &str) -> PyResult { let hash = code_hash.parse::().map_err(pyerr)?; Ok(self.db.code_by_hash(hash)?.bytecode.to_vec()) } @@ -76,7 +78,7 @@ impl EVM { } /// Get block hash by block number. - fn block_hash(&mut self, number: U256) -> PyResult> { + fn block_hash(&mut self, number: U256) -> PyResult { Ok(self.db.block_hash(number)?.to_vec()) } @@ -110,9 +112,9 @@ impl EVM { &mut self, caller: &str, to: &str, - calldata: Option>, + calldata: Option, value: Option, - ) -> PyResult> { + ) -> PyResult { let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); match self.call_raw_with_env(env) { @@ -129,9 +131,9 @@ impl EVM { &mut self, caller: &str, to: &str, - calldata: Option>, + calldata: Option, value: Option, - ) -> PyResult<(Vec, HashMap)> { + ) -> PyResult<(PyBytes, HashMap)> { let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); match self.call_raw_with_env(env) { @@ -144,7 +146,7 @@ impl EVM { fn deploy( &mut self, deployer: &str, - code: Option>, + code: Option, value: Option, _abi: Option<&str>, ) -> PyResult { From 2085ed5e13f100eb47c1cd5edc56f2001ef2fdef Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 09:47:01 +0100 Subject: [PATCH 10/33] Save the full context and execution result --- pyrevm.pyi | 13 ++ pytest/test.py | 26 +++- src/database.rs | 9 +- src/empty_db_wrapper.rs | 2 +- src/evm.rs | 226 ++++++++++++++++++++++------------ src/types/checkpoint.rs | 17 +++ src/types/evm_env.rs | 1 - src/types/execution_result.rs | 73 +++++++++++ src/types/mod.rs | 8 +- 9 files changed, 283 insertions(+), 92 deletions(-) create mode 100644 src/types/checkpoint.rs create mode 100644 src/types/execution_result.rs diff --git a/pyrevm.pyi b/pyrevm.pyi index 6662be0..c241e8b 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -78,6 +78,14 @@ class Env: @property def tx(self: "AccountInfo") -> Optional[TxEnv]: ... + +class JournalCheckpoint: + @property + def log_i(self) -> int: ... + @property + def journal_i(self) -> int: ... + + class AccountInfo: def __new__( cls: Type["AccountInfo"], @@ -113,6 +121,11 @@ class EVM: :param spec_id: The spec ID. """ + def snapshot(self: "EVM") -> JournalCheckpoint: ... + + def revert(self: "EVM", checkpoint: JournalCheckpoint) -> None: ... + def commit(self: "EVM") -> None: ... + def basic(self: "EVM", address: str) -> AccountInfo: """ Returns the basic account info for the given address. diff --git a/pytest/test.py b/pytest/test.py index 55a88e6..d27ccb9 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -99,11 +99,11 @@ def test_balances_fork(): vb_before = evm.basic(address) assert vb_before.balance == 955628344913799071315 - AMT = 10000 - evm.set_balance(address, AMT) + amount = 10000 + evm.set_balance(address, amount) - assert evm.get_balance(address) == AMT - assert evm.basic(address).balance == AMT + assert evm.get_balance(address) == amount + assert evm.basic(address).balance == amount @pytest.mark.parametrize("kwargs", KWARG_CASES) @@ -146,6 +146,24 @@ def test_call_committing(kwargs): assert int.from_bytes(result, "big") == 171 +def test_call_revert(): + evm = EVM() + amount = 10000 + evm.set_balance(address2, amount) + + snapshot = evm.snapshot() + evm.call_raw_committing( + caller=address2, + to=address, + value=amount, + ) + + assert evm.get_balance(address) == amount + evm.revert(snapshot) + assert evm.get_balance(address) == 0 + assert evm.get_balance(address2) == amount + + @pytest.mark.parametrize("kwargs", KWARG_CASES) def test_call_empty_result(kwargs): evm = EVM(**kwargs) diff --git a/src/database.rs b/src/database.rs index 6c09cd4..165a524 100644 --- a/src/database.rs +++ b/src/database.rs @@ -21,28 +21,29 @@ type ForkDB = CacheDB>>; /// A wrapper around the `CacheDB` and `EthersDB` to provide a common interface /// without needing dynamic lifetime and generic parameters (unsupported in PyO3) #[derive(Clone, Debug)] -pub enum DB { +pub(crate) enum DB { Memory(Box), Fork(Box), } impl DB { - pub fn new_memory() -> Self { + pub(crate) fn new_memory() -> Self { DB::Memory(Box::new(MemDB::new(EmptyDBWrapper::default()))) } - pub fn new_fork( + pub(crate) fn new_fork( fork_url: &str, fork_block_number: Option<&str>, ) -> PyResult { let provider = Provider::::try_from(fork_url).map_err(pyerr)?; let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; let db = EthersDB::new(Arc::new(provider), block).unwrap(); + // todo: do we need to get the blockEnv from the client? Ok(DB::Fork(Box::new(CacheDB::new(db)))) } /// Insert account info but not override storage - pub fn insert_account_info(&mut self, address: Address, info: AccountInfo) { + pub(crate) fn insert_account_info(&mut self, address: Address, info: AccountInfo) { match self { DB::Memory(db) => db.insert_account_info(address, info), DB::Fork(db) => db.insert_account_info(address, info), diff --git a/src/empty_db_wrapper.rs b/src/empty_db_wrapper.rs index de7a235..da5fb04 100644 --- a/src/empty_db_wrapper.rs +++ b/src/empty_db_wrapper.rs @@ -10,7 +10,7 @@ use revm::primitives::{Address, B256, U256}; /// Copied from Foundry: https://github.com/foundry-rs/foundry/blob/9e3ab9b3aff21c6e5ef/crates/evm/core/src/backend/in_memory_db.rs#L83-L92 #[derive(Clone, Debug, Default)] -pub struct EmptyDBWrapper(EmptyDB); +pub(crate) struct EmptyDBWrapper(EmptyDB); impl DatabaseRef for EmptyDBWrapper { type Error = Infallible; diff --git a/src/evm.rs b/src/evm.rs index 8da43fe..777fe52 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,34 +1,33 @@ use std::collections::HashMap; use std::fmt::Debug; -use std::io::stdout; -use pyo3::{PyErr, pymethods, PyResult, pyclass}; -use pyo3::ffi::PySys_WriteStdout; +use std::mem::{replace}; -use revm::{Database, Evm, inspector_handle_register, primitives::U256}; +use pyo3::{pyclass, PyErr, pymethods, PyResult}; +use pyo3::exceptions::{PyKeyError, PyOverflowError}; +use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::DatabaseCommit; +use revm::inspectors::TracerEip3155; use revm::precompile::{Address, Bytes}; -use revm::precompile::B256; -use revm::primitives::{AccountInfo as RevmAccountInfo, BlockEnv, CreateScheme, Env as RevmEnv, EnvWithHandlerCfg, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::{ExecutionResult as RevmExecutionResult, BlockEnv, CreateScheme, Env as RevmEnv, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; -use revm::inspectors::TracerEip3155; -use tracing::{trace, warn}; +use tracing::{trace}; -use crate::{types::{AccountInfo, Env}, utils::{addr, pydict, pyerr}}; +use crate::{types::{ExecutionResult, AccountInfo, Env, JournalCheckpoint}, utils::{addr, pydict, pyerr}}; use crate::database::DB; use crate::pystdout::PySysStdout; // In Py03 we use vec to represent bytes type PyBytes = Vec; -#[derive(Clone, Debug)] +#[derive(Debug)] #[pyclass] pub struct EVM { - /// The underlying `Database` that contains the EVM storage. - pub db: DB, - /// The EVM environment. - pub env: RevmEnv, - /// the current handler configuration - pub handler_cfg: HandlerCfg, + /// Context of execution. + context: EvmContext, + + /// Handler configuration. + handler_cfg: HandlerCfg, + /// The gas limit for calls and deployments. This is different from the gas limit imposed by /// the passed in environment, as those limits are used by the EVM for certain opcodes like /// `gaslimit`. @@ -36,13 +35,20 @@ pub struct EVM { /// whether to trace the execution to stdout tracing: bool, + + /// Checkpoints for reverting state + /// We cannot use Revm's checkpointing mechanism as it is not serializable + checkpoints: HashMap, + + /// The result of the last transaction + result: Option, } #[pymethods] impl EVM { /// Create a new EVM instance. #[new] - #[pyo3(signature = (env=None, fork_url=None, fork_block_number=None, gas_limit=18446744073709551615, tracing=false, spec_id="SHANGHAI"))] + #[pyo3(signature = (env = None, fork_url = None, fork_block_number = None, gas_limit = 18446744073709551615, tracing = false, spec_id = "SHANGHAI"))] fn new( env: Option, fork_url: Option<&str>, @@ -51,35 +57,64 @@ impl EVM { tracing: bool, spec_id: &str, ) -> PyResult { + let spec = SpecId::from(spec_id); + let env = env.unwrap_or_default().into(); + let db = fork_url.map(|url| DB::new_fork(url, fork_block_number)).unwrap_or(Ok(DB::new_memory()))?; + + let Evm { context, .. } = Evm::builder() + .with_env(Box::new(env)) + .with_db(db) + .build(); Ok(EVM { - db: fork_url.map(|url| DB::new_fork(url, fork_block_number)).unwrap_or(Ok(DB::new_memory()))?, - env: env.unwrap_or_default().into(), + context: context.evm, gas_limit: U256::from(gas_limit), - handler_cfg: HandlerCfg::new(SpecId::from(spec_id)), + handler_cfg: HandlerCfg::new(spec), tracing, + checkpoints: HashMap::new(), + result: None, }) } - /// Get basic account information. - fn basic(&mut self, address: &str) -> PyResult { - Ok(self.db.basic(addr(address)?)?.unwrap_or_default().into()) + fn snapshot(&mut self) -> PyResult { + let checkpoint = JournalCheckpoint { + log_i: self.context.journaled_state.logs.len(), + journal_i: self.context.journaled_state.journal.len(), + }; + self.checkpoints.insert(checkpoint, self.context.journaled_state.checkpoint()); + Ok(checkpoint) } - /// Get account code by its hash. - #[pyo3(signature = (code_hash))] - fn code_by_hash(&mut self, code_hash: &str) -> PyResult { - let hash = code_hash.parse::().map_err(pyerr)?; - Ok(self.db.code_by_hash(hash)?.bytecode.to_vec()) + fn revert(&mut self, checkpoint: JournalCheckpoint) -> PyResult<()> { + if self.context.journaled_state.depth == 0 { + return Err(PyOverflowError::new_err(format!("No checkpoint to revert to: {:?}", self.context.journaled_state))); + } + + if let Some(revm_checkpoint) = self.checkpoints.remove(&checkpoint) { + self.context.journaled_state.checkpoint_revert(revm_checkpoint); + Ok(()) + } else { + Err(PyKeyError::new_err("Invalid checkpoint")) + } + } + + fn commit(&mut self) { + self.context.journaled_state.checkpoint_commit(); + } + + /// Get basic account information. + fn basic(&mut self, address: &str) -> PyResult { + let (account, _) = self.context.load_account(addr(address)?).map_err(pyerr)?; + Ok(account.info.clone().into()) } /// Get storage value of address at index. fn storage(&mut self, address: &str, index: U256) -> PyResult { - Ok(self.db.storage(addr(address)?, index)?) + Ok(self.context.db.storage(addr(address)?, index)?) } /// Get block hash by block number. fn block_hash(&mut self, number: U256) -> PyResult { - Ok(self.db.block_hash(number)?.to_vec()) + Ok(self.context.block_hash(number).map_err(pyerr)?.to_vec()) } /// Inserts the provided account information in the database at the specified address. @@ -88,26 +123,32 @@ impl EVM { address: &str, info: AccountInfo, ) -> PyResult<()> { - self.db.insert_account_info(addr(address)?, info.clone().into()); + self.context.db.insert_account_info(addr(address)?, info.clone().into()); Ok(()) } /// Set the balance of a given address. fn set_balance(&mut self, address: &str, balance: U256) -> PyResult<()> { - let mut info = self.db.basic(addr(address)?)?.unwrap_or_default(); - info.balance = balance; - self.db.insert_account_info(addr(address)?, info); + let address_ = addr(address)?; + let account = { + let (account, _) = self.context.load_account(address_).map_err(pyerr)?; + account.info.balance = balance; + account.clone() + }; + self.context.db.insert_account_info(address_, account.info.clone()); + self.context.journaled_state.state.insert(address_, account); + self.context.journaled_state.touch(&address_); Ok(()) } /// Retrieve the balance of a given address. fn get_balance(&mut self, address: &str) -> PyResult { - let RevmAccountInfo { balance, .. } = self.db.basic(addr(address)?)?.unwrap_or_default(); + let (balance, _) = self.context.balance(addr(address)?).map_err(pyerr)?; Ok(balance) } /// runs a raw call and returns the result - #[pyo3(signature = (caller, to, calldata=None, value=None))] + #[pyo3(signature = (caller, to, calldata = None, value = None))] pub fn call_raw_committing( &mut self, caller: &str, @@ -119,14 +160,14 @@ impl EVM { match self.call_raw_with_env(env) { Ok((data, state)) => { - self.db.commit(state); + self.context.db.commit(state); Ok(data.to_vec()) - }, + } Err(e) => Err(e), } } - #[pyo3(signature = (caller, to, calldata=None, value=None))] + #[pyo3(signature = (caller, to, calldata = None, value = None))] pub fn call_raw( &mut self, caller: &str, @@ -154,28 +195,42 @@ impl EVM { match self.deploy_with_env(env) { Ok((address, state)) => { - self.db.commit(state); + self.context.db.commit(state); Ok(format!("{:?}", address)) - }, + } Err(e) => Err(e), } } #[getter] fn env(&self) -> Env { - self.env.clone().into() + (*self.context.env).clone().into() } #[getter] fn tracing(&self) -> bool { self.tracing } + + #[getter] + fn result(&self) -> Option { + self.result.clone().map(|r| r.into()) + } + + #[getter] + fn journal_depth(&self) -> usize { + self.context.journaled_state.depth + } + #[getter] + fn journal_len(&self) -> usize { + self.context.journaled_state.journal.len() + } } impl EVM { /// Creates the environment to use when executing a transaction in a test context /// - /// If using a backend with cheatcodes, `tx.gas_price` and `block.number` will be overwritten by + /// If using a backend with cheat codes, `tx.gas_price` and `block.number` will be overwritten by /// the cheatcode state inbetween calls. fn build_test_env( &self, @@ -183,16 +238,16 @@ impl EVM { transact_to: TransactTo, data: Bytes, value: U256, - ) -> EnvWithHandlerCfg { - let env = revm::primitives::Env { - cfg: self.env.cfg.clone(), + ) -> RevmEnv { + RevmEnv { + cfg: self.context.env.cfg.clone(), // We always set the gas price to 0, so we can execute the transaction regardless of // network conditions - the actual gas price is kept in `evm.block` and is applied by // the cheatcode handler if it is enabled block: BlockEnv { basefee: U256::ZERO, gas_limit: self.gas_limit, - ..self.env.block.clone() + ..self.context.env.block.clone() }, tx: TxEnv { caller, @@ -203,16 +258,14 @@ impl EVM { gas_price: U256::ZERO, gas_priority_fee: None, gas_limit: self.gas_limit.to(), - ..self.env.tx.clone() + ..self.context.env.tx.clone() }, - }; - - EnvWithHandlerCfg::new_with_spec_id(Box::new(env), self.handler_cfg.spec_id) + } } /// Deploys a contract using the given `env` and commits the new state to the underlying /// database - fn deploy_with_env(&mut self, env: EnvWithHandlerCfg) -> PyResult<(Address, State)> { + fn deploy_with_env(&mut self, env: RevmEnv) -> PyResult<(Address, State)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Create(_)), "Expect create transaction" @@ -222,21 +275,19 @@ impl EVM { let ResultAndState { result, state } = self.run_env(env)?; match &result { - Success { reason, gas_used, gas_refunded, logs, output } => { - warn!(reason=?reason, gas_used, gas_refunded, "contract deployed"); + Success { output, .. } => { match output { Output::Create(_, address) => { Ok((address.unwrap(), state)) } _ => Err(pyerr("Invalid output")), } - }, + } _ => Err(pyerr(result.clone())), } } - fn call_raw_with_env(&mut self, env: EnvWithHandlerCfg) -> PyResult<(Bytes, State)> - { + fn call_raw_with_env(&mut self, env: RevmEnv) -> PyResult<(Bytes, State)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), "Expect call transaction" @@ -246,36 +297,51 @@ impl EVM { let ResultAndState { result, state } = self.run_env(env)?; match &result { - Success { reason, gas_used, gas_refunded, logs, output } => { + Success { output, .. } => { let data = output.clone().into_data(); - trace!(reason=?reason, gas_used, gas_refunded, "call done"); Ok((data, state)) - }, + } // todo: state might have changed even if the call failed _ => Err(pyerr(result.clone())), } } - fn run_env(&mut self, env: EnvWithHandlerCfg) -> Result + fn run_env(&mut self, env: RevmEnv) -> Result { - let builder = Evm::builder() - .with_db(&mut self.db); - - let result = - if self.tracing { - let tracer = TracerEip3155::new(Box::new(PySysStdout {}), true); - builder - .with_external_context(tracer) - .with_env_with_handler_cfg(env) - .append_handler_register(inspector_handle_register) - .build() - .transact() - } else { - builder - .with_env_with_handler_cfg(env) - .build() - .transact() - }; - Ok(result.map_err(pyerr)?) + self.context.env = Box::new(env); + + // temporarily take the context out of the EVM instance + let evm_context: EvmContext = replace(&mut self.context, EvmContext::new(DB::new_memory())); + + let (result_and_state, evm_context) = if self.tracing { + let tracer = TracerEip3155::new(Box::new(PySysStdout {}), true); + let mut evm = Evm::builder() + .with_context_with_handler_cfg(ContextWithHandlerCfg { + cfg: self.handler_cfg, + context: Context { + evm: evm_context, + external: tracer, + }, + }) + .append_handler_register(inspector_handle_register) + .build(); + + (evm.transact().map_err(pyerr)?, evm.context.evm) + } else { + let mut evm = Evm::builder() + .with_context_with_handler_cfg(ContextWithHandlerCfg { + cfg: self.handler_cfg, + context: Context { + evm: evm_context, + external: (), + }, + }) + .build(); + + (evm.transact().map_err(pyerr)?, evm.context.evm) + }; + self.context = evm_context; + self.result = Some(result_and_state.result.clone()); + Ok(result_and_state) } } diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs new file mode 100644 index 0000000..5939566 --- /dev/null +++ b/src/types/checkpoint.rs @@ -0,0 +1,17 @@ +use std::hash::{Hash, Hasher}; + +use pyo3::pyclass; + +#[pyclass(get_all)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct JournalCheckpoint{ + pub log_i: usize, + pub journal_i: usize, +} + +impl Hash for JournalCheckpoint { + fn hash(&self, state: &mut H) { + self.log_i.hash(state); + self.journal_i.hash(state); + } +} diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 63c2813..65d06f9 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -4,7 +4,6 @@ use revm::primitives::{BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv a #[pyclass] #[derive(Clone, Debug, Default)] - pub struct Env(RevmEnv); #[pymethods] diff --git a/src/types/execution_result.rs b/src/types/execution_result.rs new file mode 100644 index 0000000..db039d2 --- /dev/null +++ b/src/types/execution_result.rs @@ -0,0 +1,73 @@ +use pyo3::{pyclass, pymethods}; +use revm::primitives::{ExecutionResult as RevmExecutionResult, HaltReason, OutOfGasError, SuccessReason}; + +// pub struct Log(RevmLog); + + +#[derive(Debug)] +#[pyclass(get_all)] +pub struct ExecutionResult { + is_success: bool, + is_halt: bool, + reason: String, + gas_used: u64, + gas_refunded: u64, + // TODO: logs: Vec, +} + +#[pymethods] +impl ExecutionResult {} + +impl From for ExecutionResult { + fn from(result: RevmExecutionResult) -> Self { + ExecutionResult { + is_success: result.is_success(), + is_halt: result.is_halt(), + reason: match result { + RevmExecutionResult::Success { reason, .. } => match reason { + SuccessReason::Stop => String::from("Stop"), + SuccessReason::Return => String::from("Return"), + SuccessReason::SelfDestruct => String::from("SelfDestruct"), + } + RevmExecutionResult::Revert { .. } => String::from("Revert"), + RevmExecutionResult::Halt { reason, .. } => match reason { + HaltReason::OutOfGas(out_of_gas) => match out_of_gas { + OutOfGasError::Basic => String::from("OutOfGas:Basic"), + OutOfGasError::MemoryLimit => String::from("OutOfGas:MemoryLimit"), + OutOfGasError::Memory => String::from("OutOfGas:Memory"), + OutOfGasError::Precompile => String::from("OutOfGas:Precompile"), + OutOfGasError::InvalidOperand => String::from("OutOfGas:InvalidOperand"), + }, + HaltReason::OpcodeNotFound => String::from("OpcodeNotFound"), + HaltReason::InvalidFEOpcode => String::from("InvalidFEOpcode"), + HaltReason::InvalidJump => String::from("InvalidJump"), + HaltReason::NotActivated => String::from("NotActivated"), + HaltReason::StackUnderflow => String::from("StackUnderflow"), + HaltReason::StackOverflow => String::from("StackOverflow"), + HaltReason::OutOfOffset => String::from("OutOfOffset"), + HaltReason::CreateCollision => String::from("CreateCollision"), + HaltReason::PrecompileError => String::from("PrecompileError"), + HaltReason::NonceOverflow => String::from("NonceOverflow"), + HaltReason::CreateContractSizeLimit => String::from("CreateContractSizeLimit"), + HaltReason::CreateContractStartingWithEF => String::from("CreateContractStartingWithEF"), + HaltReason::CreateInitCodeSizeLimit => String::from("CreateInitCodeSizeLimit"), + HaltReason::OverflowPayment => String::from("OverflowPayment"), + HaltReason::StateChangeDuringStaticCall => String::from("StateChangeDuringStaticCall"), + HaltReason::CallNotAllowedInsideStatic => String::from("CallNotAllowedInsideStatic"), + HaltReason::OutOfFunds => String::from("OutOfFunds"), + HaltReason::CallTooDeep => String::from("CallTooDeep"), + _ => String::from("Unknown"), + } + }, + gas_used: match result { + RevmExecutionResult::Success { gas_used, .. } => gas_used, + RevmExecutionResult::Revert { gas_used, .. } => gas_used, + RevmExecutionResult::Halt { gas_used, .. } => gas_used, + }, + gas_refunded: match result { + RevmExecutionResult::Success { gas_refunded, .. } => gas_refunded, + _ => u64::default(), + }, + } + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 0a905c0..afa118f 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,5 +1,9 @@ -mod evm_env; +pub use checkpoint::*; pub use evm_env::*; +pub use info::*; +pub use execution_result::*; +mod evm_env; mod info; -pub use info::AccountInfo; +mod checkpoint; +mod execution_result; From ef712be255ebf51e010e1f819facda25070066ef Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 15:57:07 +0100 Subject: [PATCH 11/33] Clone the DB as checkpoint --- src/database.rs | 11 ++++- src/evm.rs | 89 +++++++++++++++++------------------ src/types/checkpoint.rs | 17 ------- src/types/execution_result.rs | 1 - src/types/mod.rs | 8 +++- src/utils.rs | 10 +++- 6 files changed, 66 insertions(+), 70 deletions(-) delete mode 100644 src/types/checkpoint.rs diff --git a/src/database.rs b/src/database.rs index 165a524..d3b7252 100644 --- a/src/database.rs +++ b/src/database.rs @@ -5,9 +5,9 @@ use ethers_core::types::BlockId; use ethers_providers::{Http, Provider}; use pyo3::{PyErr, PyResult}; use revm::Database; -use revm::db::{CacheDB, EthersDB}; +use revm::db::{CacheDB, DbAccount, EthersDB}; use revm::precompile::{Address, B256}; -use revm::primitives::{AccountInfo, Bytecode, State}; +use revm::primitives::{AccountInfo, Bytecode, HashMap, State}; use revm_interpreter::primitives::db::{DatabaseCommit, DatabaseRef}; use ruint::aliases::U256; @@ -49,6 +49,13 @@ impl DB { DB::Fork(db) => db.insert_account_info(address, info), } } + + pub(crate) fn get_accounts(&self) -> &HashMap { + match self { + DB::Memory(db) => &db.accounts, + DB::Fork(db) => &db.accounts, + } + } } impl Database for DB { diff --git a/src/evm.rs b/src/evm.rs index 777fe52..dcedb76 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,23 +1,23 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fmt::Debug; -use std::mem::{replace}; +use std::mem::replace; use pyo3::{pyclass, PyErr, pymethods, PyResult}; -use pyo3::exceptions::{PyKeyError, PyOverflowError}; -use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; +use pyo3::exceptions::{PyKeyError}; +use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, inspector_handle_register, primitives::U256}; use revm::DatabaseCommit; use revm::inspectors::TracerEip3155; use revm::precompile::{Address, Bytes}; -use revm::primitives::{ExecutionResult as RevmExecutionResult, BlockEnv, CreateScheme, Env as RevmEnv, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; -use tracing::{trace}; +use tracing::trace; -use crate::{types::{ExecutionResult, AccountInfo, Env, JournalCheckpoint}, utils::{addr, pydict, pyerr}}; +use crate::{types::{AccountInfo, Env, ExecutionResult}, utils::{addr, pydict, pyerr}}; use crate::database::DB; use crate::pystdout::PySysStdout; +use crate::types::{PyBytes, PyDB, Checkpoint}; +use crate::utils::to_hashmap; -// In Py03 we use vec to represent bytes -type PyBytes = Vec; #[derive(Debug)] #[pyclass] @@ -37,8 +37,9 @@ pub struct EVM { tracing: bool, /// Checkpoints for reverting state - /// We cannot use Revm's checkpointing mechanism as it is not serializable - checkpoints: HashMap, + /// We cannot use Revm's checkpointing mechanism as it is limited to transaction scope + checkpoints: HashMap, + checkpoint: Checkpoint, /// The result of the last transaction result: Option, @@ -48,7 +49,7 @@ pub struct EVM { impl EVM { /// Create a new EVM instance. #[new] - #[pyo3(signature = (env = None, fork_url = None, fork_block_number = None, gas_limit = 18446744073709551615, tracing = false, spec_id = "SHANGHAI"))] + #[pyo3(signature = (env = None, fork_url = None, fork_block_number = None, gas_limit = 18446744073709551615, tracing = false, spec_id = "LATEST"))] fn new( env: Option, fork_url: Option<&str>, @@ -71,40 +72,34 @@ impl EVM { handler_cfg: HandlerCfg::new(spec), tracing, checkpoints: HashMap::new(), + checkpoint: 0, result: None, }) } - fn snapshot(&mut self) -> PyResult { - let checkpoint = JournalCheckpoint { - log_i: self.context.journaled_state.logs.len(), - journal_i: self.context.journaled_state.journal.len(), - }; - self.checkpoints.insert(checkpoint, self.context.journaled_state.checkpoint()); - Ok(checkpoint) + fn snapshot(&mut self) -> PyResult { + self.checkpoint += 1; + self.checkpoints.insert(self.checkpoint, self.context.db.clone()); + Ok(self.checkpoint) } - fn revert(&mut self, checkpoint: JournalCheckpoint) -> PyResult<()> { - if self.context.journaled_state.depth == 0 { - return Err(PyOverflowError::new_err(format!("No checkpoint to revert to: {:?}", self.context.journaled_state))); - } - - if let Some(revm_checkpoint) = self.checkpoints.remove(&checkpoint) { - self.context.journaled_state.checkpoint_revert(revm_checkpoint); + fn revert(&mut self, checkpoint: Checkpoint) -> PyResult<()> { + if let Some(db) = self.checkpoints.remove(&checkpoint) { + self.context.db = db; Ok(()) } else { - Err(PyKeyError::new_err("Invalid checkpoint")) + Err(PyKeyError::new_err(format!("Invalid checkpoint {0}", checkpoint))) } } fn commit(&mut self) { - self.context.journaled_state.checkpoint_commit(); + self.checkpoints.clear(); } /// Get basic account information. fn basic(&mut self, address: &str) -> PyResult { - let (account, _) = self.context.load_account(addr(address)?).map_err(pyerr)?; - Ok(account.info.clone().into()) + let info = self.context.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); + Ok(info.clone().into()) } /// Get storage value of address at index. @@ -129,22 +124,17 @@ impl EVM { /// Set the balance of a given address. fn set_balance(&mut self, address: &str, balance: U256) -> PyResult<()> { - let address_ = addr(address)?; - let account = { - let (account, _) = self.context.load_account(address_).map_err(pyerr)?; - account.info.balance = balance; - account.clone() - }; - self.context.db.insert_account_info(address_, account.info.clone()); - self.context.journaled_state.state.insert(address_, account); - self.context.journaled_state.touch(&address_); + let target = addr(address)?; + let mut info = self.context.db.basic(target).map_err(pyerr)?.unwrap_or_default().clone(); + info.balance = balance; + self.context.db.insert_account_info(target, info); Ok(()) } /// Retrieve the balance of a given address. fn get_balance(&mut self, address: &str) -> PyResult { - let (balance, _) = self.context.balance(addr(address)?).map_err(pyerr)?; - Ok(balance) + let info = self.context.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); + Ok(info.balance) } /// runs a raw call and returns the result @@ -174,7 +164,7 @@ impl EVM { to: &str, calldata: Option, value: Option, - ) -> PyResult<(PyBytes, HashMap)> { + ) -> PyResult<(PyBytes, PyDB)> { let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); match self.call_raw_with_env(env) { @@ -218,13 +208,18 @@ impl EVM { } #[getter] - fn journal_depth(&self) -> usize { - self.context.journaled_state.depth + fn checkpoint_ids(&self) -> HashSet { + self.checkpoints.keys().cloned().collect() } - #[getter] - fn journal_len(&self) -> usize { - self.context.journaled_state.journal.len() + + fn get_checkpoints(&self) -> HashMap { + self.checkpoints.iter().map(|(k, db)| (*k, to_hashmap(db.get_accounts()))).collect() + } + + fn get_accounts(&self) -> PyDB { + to_hashmap(self.context.db.get_accounts()) } + } impl EVM { diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs deleted file mode 100644 index 5939566..0000000 --- a/src/types/checkpoint.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::hash::{Hash, Hasher}; - -use pyo3::pyclass; - -#[pyclass(get_all)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct JournalCheckpoint{ - pub log_i: usize, - pub journal_i: usize, -} - -impl Hash for JournalCheckpoint { - fn hash(&self, state: &mut H) { - self.log_i.hash(state); - self.journal_i.hash(state); - } -} diff --git a/src/types/execution_result.rs b/src/types/execution_result.rs index db039d2..15ed62d 100644 --- a/src/types/execution_result.rs +++ b/src/types/execution_result.rs @@ -56,7 +56,6 @@ impl From for ExecutionResult { HaltReason::CallNotAllowedInsideStatic => String::from("CallNotAllowedInsideStatic"), HaltReason::OutOfFunds => String::from("OutOfFunds"), HaltReason::CallTooDeep => String::from("CallTooDeep"), - _ => String::from("Unknown"), } }, gas_used: match result { diff --git a/src/types/mod.rs b/src/types/mod.rs index afa118f..889d619 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,9 +1,13 @@ -pub use checkpoint::*; +use std::collections::HashMap; pub use evm_env::*; pub use info::*; pub use execution_result::*; mod evm_env; mod info; -mod checkpoint; mod execution_result; + +// In Py03 we use vec to represent bytes +pub(crate) type PyBytes = Vec; +pub(crate) type Checkpoint = i32; +pub(crate) type PyDB = HashMap; diff --git a/src/utils.rs b/src/utils.rs index fe5a4de..c353522 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,11 @@ use pyo3::{exceptions::PyTypeError, prelude::*}; -use revm::primitives::{Address, State}; +use revm::primitives::{Address, State, HashMap as RevmHashMap}; use std::fmt::Debug; use pyo3::exceptions::PyRuntimeError; use std::collections::HashMap; +use revm::db::DbAccount; use crate::AccountInfo; +use crate::types::PyDB; pub(crate) fn addr(s: &str) -> Result { s.parse::
() @@ -27,3 +29,9 @@ pub(crate) fn pydict(res: State) -> HashMap { pub(crate) fn pyerr(err: T) -> PyErr { PyRuntimeError::new_err(format!("{:?}", err)) } + +pub(crate) fn to_hashmap(map: &RevmHashMap) -> PyDB { + map.iter().map( + |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) + ).collect() +} From 29e0d3f66e7fcc0295aa4b8c603e936ab84a731d Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 16:33:44 +0100 Subject: [PATCH 12/33] Inline transact method --- src/evm.rs | 146 +++++++++++++++++++++++++++++++--------- src/types/checkpoint.rs | 17 +++++ src/types/mod.rs | 4 +- 3 files changed, 135 insertions(+), 32 deletions(-) create mode 100644 src/types/checkpoint.rs diff --git a/src/evm.rs b/src/evm.rs index dcedb76..cc23f02 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -3,22 +3,22 @@ use std::fmt::Debug; use std::mem::replace; use pyo3::{pyclass, PyErr, pymethods, PyResult}; -use pyo3::exceptions::{PyKeyError}; -use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, inspector_handle_register, primitives::U256}; +use pyo3::exceptions::{PyKeyError, PyOverflowError}; +use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, FrameOrResult, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::DatabaseCommit; use revm::inspectors::TracerEip3155; use revm::precompile::{Address, Bytes}; use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; +use revm_interpreter::{CallInputs, CreateInputs}; use tracing::trace; -use crate::{types::{AccountInfo, Env, ExecutionResult}, utils::{addr, pydict, pyerr}}; +use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pydict, pyerr}}; use crate::database::DB; use crate::pystdout::PySysStdout; -use crate::types::{PyBytes, PyDB, Checkpoint}; +use crate::types::{PyBytes, PyDB}; use crate::utils::to_hashmap; - #[derive(Debug)] #[pyclass] pub struct EVM { @@ -37,9 +37,8 @@ pub struct EVM { tracing: bool, /// Checkpoints for reverting state - /// We cannot use Revm's checkpointing mechanism as it is limited to transaction scope - checkpoints: HashMap, - checkpoint: Checkpoint, + /// We cannot use Revm's checkpointing mechanism as it is not serializable + checkpoints: HashMap, /// The result of the last transaction result: Option, @@ -72,34 +71,40 @@ impl EVM { handler_cfg: HandlerCfg::new(spec), tracing, checkpoints: HashMap::new(), - checkpoint: 0, result: None, }) } - fn snapshot(&mut self) -> PyResult { - self.checkpoint += 1; - self.checkpoints.insert(self.checkpoint, self.context.db.clone()); - Ok(self.checkpoint) + fn snapshot(&mut self) -> PyResult { + let checkpoint = JournalCheckpoint { + log_i: self.context.journaled_state.logs.len(), + journal_i: self.context.journaled_state.journal.len(), + }; + self.checkpoints.insert(checkpoint, self.context.journaled_state.checkpoint()); + Ok(checkpoint) } - fn revert(&mut self, checkpoint: Checkpoint) -> PyResult<()> { - if let Some(db) = self.checkpoints.remove(&checkpoint) { - self.context.db = db; + fn revert(&mut self, checkpoint: JournalCheckpoint) -> PyResult<()> { + if self.context.journaled_state.depth == 0 { + return Err(PyOverflowError::new_err(format!("No checkpoint to revert to: {:?}", self.context.journaled_state))); + } + + if let Some(revm_checkpoint) = self.checkpoints.remove(&checkpoint) { + self.context.journaled_state.checkpoint_revert(revm_checkpoint); Ok(()) } else { - Err(PyKeyError::new_err(format!("Invalid checkpoint {0}", checkpoint))) + Err(PyKeyError::new_err("Invalid checkpoint")) } } fn commit(&mut self) { - self.checkpoints.clear(); + self.context.journaled_state.checkpoint_commit(); } /// Get basic account information. fn basic(&mut self, address: &str) -> PyResult { - let info = self.context.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); - Ok(info.clone().into()) + let (account, _) = self.context.load_account(addr(address)?).map_err(pyerr)?; + Ok(account.info.clone().into()) } /// Get storage value of address at index. @@ -124,17 +129,22 @@ impl EVM { /// Set the balance of a given address. fn set_balance(&mut self, address: &str, balance: U256) -> PyResult<()> { - let target = addr(address)?; - let mut info = self.context.db.basic(target).map_err(pyerr)?.unwrap_or_default().clone(); - info.balance = balance; - self.context.db.insert_account_info(target, info); + let address_ = addr(address)?; + let account = { + let (account, _) = self.context.load_account(address_).map_err(pyerr)?; + account.info.balance = balance; + account.clone() + }; + self.context.db.insert_account_info(address_, account.info.clone()); + self.context.journaled_state.state.insert(address_, account); + self.context.journaled_state.touch(&address_); Ok(()) } /// Retrieve the balance of a given address. fn get_balance(&mut self, address: &str) -> PyResult { - let info = self.context.db.basic(addr(address)?).map_err(pyerr)?.unwrap_or_default(); - Ok(info.balance) + let (balance, _) = self.context.balance(addr(address)?).map_err(pyerr)?; + Ok(balance) } /// runs a raw call and returns the result @@ -208,12 +218,17 @@ impl EVM { } #[getter] - fn checkpoint_ids(&self) -> HashSet { + fn checkpoint_ids(&self) -> HashSet { self.checkpoints.keys().cloned().collect() } - fn get_checkpoints(&self) -> HashMap { - self.checkpoints.iter().map(|(k, db)| (*k, to_hashmap(db.get_accounts()))).collect() + #[getter] + fn journal_depth(&self) -> usize { + self.context.journaled_state.depth + } + #[getter] + fn journal_len(&self) -> usize { + self.context.journaled_state.journal.len() } fn get_accounts(&self) -> PyDB { @@ -321,7 +336,7 @@ impl EVM { .append_handler_register(inspector_handle_register) .build(); - (evm.transact().map_err(pyerr)?, evm.context.evm) + (Self::call(&mut evm)?, evm.context.evm) } else { let mut evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { @@ -333,10 +348,79 @@ impl EVM { }) .build(); - (evm.transact().map_err(pyerr)?, evm.context.evm) + (Self::call(&mut evm)?, evm.context.evm) }; self.context = evm_context; self.result = Some(result_and_state.result.clone()); Ok(result_and_state) } + + fn call(evm: &mut Evm<'_, T, DB>) -> PyResult { + evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; + let initial_gas_spend = evm + .handler + .validation() + .initial_tx_gas(&evm.context.evm.env) + .map_err(pyerr)?; + evm.handler + .validation() + .tx_against_state(&mut evm.context) + .map_err(pyerr)?; + + let output = Self::transact_preverified_inner(evm, initial_gas_spend)?; + Ok(output) + // Ok(evm.handler.post_execution().end(&mut evm.context, Ok(output)).map_err(pyerr)?) + } + + fn transact_preverified_inner(evm: &mut Evm<'_, T, DB>, initial_gas_spend: u64) -> PyResult { + let ctx = &mut evm.context; + let pre_exec = evm.handler.pre_execution(); + + // load access list and beneficiary if needed. + pre_exec.load_accounts(ctx).map_err(pyerr)?; + + // load precompiles + let precompiles = pre_exec.load_precompiles(); + ctx.evm.set_precompiles(precompiles); + + // deduce caller balance with its limit. + pre_exec.deduct_caller(ctx).map_err(pyerr)?; + + let gas_limit = ctx.evm.env.tx.gas_limit - initial_gas_spend; + + let exec = evm.handler.execution(); + // call inner handling of call/create + let first_frame_or_result = match ctx.evm.env.tx.transact_to { + TransactTo::Call(_) => exec.call( + ctx, + CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + ).map_err(pyerr)?, + TransactTo::Create(_) => exec.create( + ctx, + CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + ).map_err(pyerr)?, + }; + + // Starts the main running loop. + let mut result = match first_frame_or_result { + FrameOrResult::Frame(first_frame) => evm.start_the_loop(first_frame).map_err(pyerr)?, + FrameOrResult::Result(result) => result, + }; + + let ctx = &mut evm.context; + + // handle output of call/create calls. + evm.handler + .execution() + .last_frame_return(ctx, &mut result) + .map_err(pyerr)?; + + let post_exec = evm.handler.post_execution(); + // Reimburse the caller + post_exec.reimburse_caller(ctx, result.gas()).map_err(pyerr)?; + // Reward beneficiary + post_exec.reward_beneficiary(ctx, result.gas()).map_err(pyerr)?; + // Returns output of transaction. + post_exec.output(ctx, result).map_err(pyerr) + } } diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs new file mode 100644 index 0000000..5939566 --- /dev/null +++ b/src/types/checkpoint.rs @@ -0,0 +1,17 @@ +use std::hash::{Hash, Hasher}; + +use pyo3::pyclass; + +#[pyclass(get_all)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct JournalCheckpoint{ + pub log_i: usize, + pub journal_i: usize, +} + +impl Hash for JournalCheckpoint { + fn hash(&self, state: &mut H) { + self.log_i.hash(state); + self.journal_i.hash(state); + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 889d619..52815c9 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -2,12 +2,14 @@ use std::collections::HashMap; pub use evm_env::*; pub use info::*; pub use execution_result::*; +pub use checkpoint::*; mod evm_env; mod info; mod execution_result; +mod checkpoint; + // In Py03 we use vec to represent bytes pub(crate) type PyBytes = Vec; -pub(crate) type Checkpoint = i32; pub(crate) type PyDB = HashMap; From 11ff79ad3fcb204bf65c5647168ecbe2bbaa98d1 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 16:57:58 +0100 Subject: [PATCH 13/33] Inline output method --- src/evm.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/evm.rs b/src/evm.rs index cc23f02..5059168 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -4,13 +4,13 @@ use std::mem::replace; use pyo3::{pyclass, PyErr, pymethods, PyResult}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; -use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, FrameOrResult, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; +use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::DatabaseCommit; use revm::inspectors::TracerEip3155; use revm::precompile::{Address, Bytes}; use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; -use revm_interpreter::{CallInputs, CreateInputs}; +use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; use tracing::trace; use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pydict, pyerr}}; @@ -355,7 +355,7 @@ impl EVM { Ok(result_and_state) } - fn call(evm: &mut Evm<'_, T, DB>) -> PyResult { + fn call(evm: &mut Evm<'_, EXT, DB>) -> PyResult { evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm .handler @@ -368,11 +368,10 @@ impl EVM { .map_err(pyerr)?; let output = Self::transact_preverified_inner(evm, initial_gas_spend)?; - Ok(output) - // Ok(evm.handler.post_execution().end(&mut evm.context, Ok(output)).map_err(pyerr)?) + Ok(evm.handler.post_execution().end(&mut evm.context, Ok(output)).map_err(pyerr)?) } - fn transact_preverified_inner(evm: &mut Evm<'_, T, DB>, initial_gas_spend: u64) -> PyResult { + fn transact_preverified_inner(evm: &mut Evm<'_, EXT, DB>, initial_gas_spend: u64) -> PyResult { let ctx = &mut evm.context; let pre_exec = evm.handler.pre_execution(); @@ -421,6 +420,49 @@ impl EVM { // Reward beneficiary post_exec.reward_beneficiary(ctx, result.gas()).map_err(pyerr)?; // Returns output of transaction. - post_exec.output(ctx, result).map_err(pyerr) + Self::output(ctx, result) + } + + /// Main return handle, returns the output of the transaction. + #[inline] + fn output( + context: &mut Context, + result: FrameResult, + ) -> PyResult { + replace(&mut context.evm.error, Ok(())).map_err(pyerr)?; + // used gas with refund calculated. + let gas_refunded = result.gas().refunded() as u64; + let final_gas_used = result.gas().spend() - gas_refunded; + let output = result.output(); + let instruction_result = result.into_interpreter_result(); + + // reset journal and return present state. + let (state, logs) = context.evm.journaled_state.finalize(); + + let result = match instruction_result.result.into() { + SuccessOrHalt::Success(reason) => Success { + reason, + gas_used: final_gas_used, + gas_refunded, + logs, + output, + }, + SuccessOrHalt::Revert => revm::primitives::ExecutionResult::Revert { + gas_used: final_gas_used, + output: output.into_data(), + }, + SuccessOrHalt::Halt(reason) => revm::primitives::ExecutionResult::Halt { + reason, + gas_used: final_gas_used, + }, + // Only two internal return flags. + SuccessOrHalt::FatalExternalError + | SuccessOrHalt::InternalContinue + | SuccessOrHalt::InternalCallOrCreate => { + panic!("Internal return flags should remain internal {instruction_result:?}") + } + }; + + Ok(ResultAndState { result, state }) } } From 890ef861d54229c4483f7322d3a97d6b688afd1a Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 20:45:21 +0100 Subject: [PATCH 14/33] Omit commit after execution --- README.md | 20 ++++++------- pyrevm.pyi | 18 +----------- pytest/test.py | 16 +++++------ src/evm.rs | 78 +++++++++++++++----------------------------------- 4 files changed, 41 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 3272b79..03a563a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ a transaction from `vitalik.eth`. ```python from pyrevm import * -address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # vitalik.eth +address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # vitalik.eth address2 = "0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" fork_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27" @@ -28,23 +28,23 @@ fork_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27" # set up an evm evm = EVM( # can fork from a remote node - fork_url=fork_url, + fork_url=fork_url, # can set tracing to true/false - tracing = True, + tracing=True, # can configure the environment - env = Env( - block = BlockEnv( timestamp = 100 - )) + env=Env( + block=BlockEnv(timestamp=100 + )) ); vb_before = evm.basic(address) assert vb_before != 0 # Execute the tx -evm.call_raw_committing( - caller = address, - to = address2, - value = 10000 +evm.call_raw( + caller=address, + to=address2, + value=10000 # data ); diff --git a/pyrevm.pyi b/pyrevm.pyi index c241e8b..80c9fe3 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -140,29 +140,13 @@ class EVM: :param info: The account info. """ - def call_raw_committing( - self: "EVM", - caller: str, - to: str, - calldata: Optional[bytes] = None, - value: Optional[int] = None, - ) -> bytes: - """ - Processes a raw call, committing the result to the state. - :param caller: The address of the caller. - :param to: The address of the callee. - :param calldata: The data to pass to the contract. - :param value: The value. - :return: The return data. - """ - def call_raw( self: "EVM", caller: str, to: str, calldata: Optional[bytes] = None, value: Optional[int] = None, - ) -> Tuple[bytes, dict[str, AccountInfo]]: + ) -> bytes: """ Processes a raw call, without committing the result to the state. :param caller: The address of the caller. diff --git a/pytest/test.py b/pytest/test.py index d27ccb9..1ffd42f 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -48,7 +48,7 @@ def test_revm_fork(): assert vb_before is not None # Execute the tx - evm.call_raw_committing( + evm.call_raw( caller=address, to=address2, value=10000 @@ -114,7 +114,7 @@ def test_call_raw(kwargs): assert evm.basic(address).code == info.code # mulDiv() -> 64 * 8 / 2 - result, changes = evm.call_raw( + result = evm.call_raw( caller=address2, to=address, calldata=bytes.fromhex( @@ -123,8 +123,6 @@ def test_call_raw(kwargs): ) assert int.from_bytes(result, "big") == 256 - assert changes[address].nonce == 0 - assert changes[address2].nonce == 1 @pytest.mark.parametrize("kwargs", KWARG_CASES) @@ -135,7 +133,7 @@ def test_call_committing(kwargs): ) # mulDivRoundingUp() -> 64 * 8 / 3 - result = evm.call_raw_committing( + result = evm.call_raw( caller=address2, to=address, calldata=bytes.fromhex( @@ -152,7 +150,7 @@ def test_call_revert(): evm.set_balance(address2, amount) snapshot = evm.snapshot() - evm.call_raw_committing( + evm.call_raw( caller=address2, to=address, value=amount, @@ -171,7 +169,7 @@ def test_call_empty_result(kwargs): evm.set_balance(address2, 10000) - deposit = evm.call_raw_committing( + deposit = evm.call_raw( caller=address2, to=address, value=10000, @@ -180,7 +178,7 @@ def test_call_empty_result(kwargs): assert deposit == [] - balance, _ = evm.call_raw( + balance = evm.call_raw( caller=address2, to=address, calldata=bytes.fromhex("70a08231" + encode_address(address2)), @@ -194,7 +192,7 @@ def test_tracing(capsys): evm = EVM(tracing=True) evm.insert_account_info(address, AccountInfo(code=load_contract_bin("weth_9.bin"))) evm.set_balance(address2, 10000) - evm.call_raw_committing( + evm.call_raw( caller=address2, to=address, value=10000, diff --git a/src/evm.rs b/src/evm.rs index 5059168..8fef9ec 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::mem::replace; -use pyo3::{pyclass, PyErr, pymethods, PyResult}; +use pyo3::{pyclass, pymethods, PyResult}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::DatabaseCommit; use revm::inspectors::TracerEip3155; use revm::precompile::{Address, Bytes}; use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; -use revm::primitives::ExecutionResult::Success; +use RevmExecutionResult::Success; use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; use tracing::trace; @@ -147,26 +147,6 @@ impl EVM { Ok(balance) } - /// runs a raw call and returns the result - #[pyo3(signature = (caller, to, calldata = None, value = None))] - pub fn call_raw_committing( - &mut self, - caller: &str, - to: &str, - calldata: Option, - value: Option, - ) -> PyResult { - let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - match self.call_raw_with_env(env) - { - Ok((data, state)) => { - self.context.db.commit(state); - Ok(data.to_vec()) - } - Err(e) => Err(e), - } - } - #[pyo3(signature = (caller, to, calldata = None, value = None))] pub fn call_raw( &mut self, @@ -174,11 +154,11 @@ impl EVM { to: &str, calldata: Option, value: Option, - ) -> PyResult<(PyBytes, PyDB)> { + ) -> PyResult { let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); match self.call_raw_with_env(env) { - Ok((data, state)) => Ok((data.to_vec(), pydict(state))), + Ok(data) => Ok(data.to_vec()), Err(e) => Err(e), } } @@ -194,10 +174,7 @@ impl EVM { let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); match self.deploy_with_env(env) { - Ok((address, state)) => { - self.context.db.commit(state); - Ok(format!("{:?}", address)) - } + Ok(address) => Ok(format!("{:?}", address)), Err(e) => Err(e), } } @@ -275,20 +252,20 @@ impl EVM { /// Deploys a contract using the given `env` and commits the new state to the underlying /// database - fn deploy_with_env(&mut self, env: RevmEnv) -> PyResult<(Address, State)> { + fn deploy_with_env(&mut self, env: RevmEnv) -> PyResult
{ debug_assert!( matches!(env.tx.transact_to, TransactTo::Create(_)), "Expect create transaction" ); trace!(sender=?env.tx.caller, "deploying contract"); - let ResultAndState { result, state } = self.run_env(env)?; + let result = self.run_env(env)?; match &result { Success { output, .. } => { match output { Output::Create(_, address) => { - Ok((address.unwrap(), state)) + Ok(address.unwrap()) } _ => Err(pyerr("Invalid output")), } @@ -297,33 +274,28 @@ impl EVM { } } - fn call_raw_with_env(&mut self, env: RevmEnv) -> PyResult<(Bytes, State)> { + fn call_raw_with_env(&mut self, env: RevmEnv) -> PyResult { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), "Expect call transaction" ); trace!(sender=?env.tx.caller, "deploying contract"); - let ResultAndState { result, state } = self.run_env(env)?; - + let result = self.run_env(env)?; match &result { - Success { output, .. } => { - let data = output.clone().into_data(); - Ok((data, state)) - } - // todo: state might have changed even if the call failed + Success { output, .. } => Ok(output.clone().into_data()), _ => Err(pyerr(result.clone())), } } - fn run_env(&mut self, env: RevmEnv) -> Result + fn run_env(&mut self, env: RevmEnv) -> PyResult { self.context.env = Box::new(env); // temporarily take the context out of the EVM instance let evm_context: EvmContext = replace(&mut self.context, EvmContext::new(DB::new_memory())); - let (result_and_state, evm_context) = if self.tracing { + let (result, evm_context) = if self.tracing { let tracer = TracerEip3155::new(Box::new(PySysStdout {}), true); let mut evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { @@ -351,11 +323,11 @@ impl EVM { (Self::call(&mut evm)?, evm.context.evm) }; self.context = evm_context; - self.result = Some(result_and_state.result.clone()); - Ok(result_and_state) + self.result = Some(result.clone()); + Ok(result) } - fn call(evm: &mut Evm<'_, EXT, DB>) -> PyResult { + fn call(evm: &mut Evm<'_, EXT, DB>) -> PyResult { evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm .handler @@ -367,11 +339,10 @@ impl EVM { .tx_against_state(&mut evm.context) .map_err(pyerr)?; - let output = Self::transact_preverified_inner(evm, initial_gas_spend)?; - Ok(evm.handler.post_execution().end(&mut evm.context, Ok(output)).map_err(pyerr)?) + Self::transact_preverified_inner(evm, initial_gas_spend) } - fn transact_preverified_inner(evm: &mut Evm<'_, EXT, DB>, initial_gas_spend: u64) -> PyResult { + fn transact_preverified_inner(evm: &mut Evm<'_, EXT, DB>, initial_gas_spend: u64) -> PyResult { let ctx = &mut evm.context; let pre_exec = evm.handler.pre_execution(); @@ -428,7 +399,7 @@ impl EVM { fn output( context: &mut Context, result: FrameResult, - ) -> PyResult { + ) -> PyResult { replace(&mut context.evm.error, Ok(())).map_err(pyerr)?; // used gas with refund calculated. let gas_refunded = result.gas().refunded() as u64; @@ -436,22 +407,19 @@ impl EVM { let output = result.output(); let instruction_result = result.into_interpreter_result(); - // reset journal and return present state. - let (state, logs) = context.evm.journaled_state.finalize(); - let result = match instruction_result.result.into() { SuccessOrHalt::Success(reason) => Success { reason, gas_used: final_gas_used, gas_refunded, - logs, + logs: vec![], // todo: logs output, }, - SuccessOrHalt::Revert => revm::primitives::ExecutionResult::Revert { + SuccessOrHalt::Revert => RevmExecutionResult::Revert { gas_used: final_gas_used, output: output.into_data(), }, - SuccessOrHalt::Halt(reason) => revm::primitives::ExecutionResult::Halt { + SuccessOrHalt::Halt(reason) => RevmExecutionResult::Halt { reason, gas_used: final_gas_used, }, @@ -463,6 +431,6 @@ impl EVM { } }; - Ok(ResultAndState { result, state }) + Ok(result) } } From 50c4581463ff3210578c5c3898d8feaca7202433 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 20:57:41 +0100 Subject: [PATCH 15/33] Refactor --- src/evm.rs | 133 ++++-------------------------------------------- src/executor.rs | 110 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/utils.rs | 10 +--- 4 files changed, 123 insertions(+), 131 deletions(-) create mode 100644 src/executor.rs diff --git a/src/evm.rs b/src/evm.rs index 8fef9ec..363c4e1 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -4,17 +4,16 @@ use std::mem::replace; use pyo3::{pyclass, pymethods, PyResult}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; -use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; -use revm::DatabaseCommit; +use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::inspectors::TracerEip3155; use revm::precompile::{Address, Bytes}; -use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, ResultAndState, SpecId, State, TransactTo, TxEnv}; +use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; use RevmExecutionResult::Success; -use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; use tracing::trace; -use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pydict, pyerr}}; +use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; use crate::database::DB; +use crate::executor::evm_call; use crate::pystdout::PySysStdout; use crate::types::{PyBytes, PyDB}; use crate::utils::to_hashmap; @@ -264,10 +263,8 @@ impl EVM { match &result { Success { output, .. } => { match output { - Output::Create(_, address) => { - Ok(address.unwrap()) - } - _ => Err(pyerr("Invalid output")), + Output::Create(_, address) => Ok(address.unwrap()), + _ => Err(pyerr(output.clone())), } } _ => Err(pyerr(result.clone())), @@ -297,7 +294,7 @@ impl EVM { let (result, evm_context) = if self.tracing { let tracer = TracerEip3155::new(Box::new(PySysStdout {}), true); - let mut evm = Evm::builder() + let evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { cfg: self.handler_cfg, context: Context { @@ -307,10 +304,9 @@ impl EVM { }) .append_handler_register(inspector_handle_register) .build(); - - (Self::call(&mut evm)?, evm.context.evm) + evm_call(evm) } else { - let mut evm = Evm::builder() + let evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { cfg: self.handler_cfg, context: Context { @@ -320,117 +316,10 @@ impl EVM { }) .build(); - (Self::call(&mut evm)?, evm.context.evm) - }; + evm_call(evm) + }?; self.context = evm_context; self.result = Some(result.clone()); Ok(result) } - - fn call(evm: &mut Evm<'_, EXT, DB>) -> PyResult { - evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; - let initial_gas_spend = evm - .handler - .validation() - .initial_tx_gas(&evm.context.evm.env) - .map_err(pyerr)?; - evm.handler - .validation() - .tx_against_state(&mut evm.context) - .map_err(pyerr)?; - - Self::transact_preverified_inner(evm, initial_gas_spend) - } - - fn transact_preverified_inner(evm: &mut Evm<'_, EXT, DB>, initial_gas_spend: u64) -> PyResult { - let ctx = &mut evm.context; - let pre_exec = evm.handler.pre_execution(); - - // load access list and beneficiary if needed. - pre_exec.load_accounts(ctx).map_err(pyerr)?; - - // load precompiles - let precompiles = pre_exec.load_precompiles(); - ctx.evm.set_precompiles(precompiles); - - // deduce caller balance with its limit. - pre_exec.deduct_caller(ctx).map_err(pyerr)?; - - let gas_limit = ctx.evm.env.tx.gas_limit - initial_gas_spend; - - let exec = evm.handler.execution(); - // call inner handling of call/create - let first_frame_or_result = match ctx.evm.env.tx.transact_to { - TransactTo::Call(_) => exec.call( - ctx, - CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), - ).map_err(pyerr)?, - TransactTo::Create(_) => exec.create( - ctx, - CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), - ).map_err(pyerr)?, - }; - - // Starts the main running loop. - let mut result = match first_frame_or_result { - FrameOrResult::Frame(first_frame) => evm.start_the_loop(first_frame).map_err(pyerr)?, - FrameOrResult::Result(result) => result, - }; - - let ctx = &mut evm.context; - - // handle output of call/create calls. - evm.handler - .execution() - .last_frame_return(ctx, &mut result) - .map_err(pyerr)?; - - let post_exec = evm.handler.post_execution(); - // Reimburse the caller - post_exec.reimburse_caller(ctx, result.gas()).map_err(pyerr)?; - // Reward beneficiary - post_exec.reward_beneficiary(ctx, result.gas()).map_err(pyerr)?; - // Returns output of transaction. - Self::output(ctx, result) - } - - /// Main return handle, returns the output of the transaction. - #[inline] - fn output( - context: &mut Context, - result: FrameResult, - ) -> PyResult { - replace(&mut context.evm.error, Ok(())).map_err(pyerr)?; - // used gas with refund calculated. - let gas_refunded = result.gas().refunded() as u64; - let final_gas_used = result.gas().spend() - gas_refunded; - let output = result.output(); - let instruction_result = result.into_interpreter_result(); - - let result = match instruction_result.result.into() { - SuccessOrHalt::Success(reason) => Success { - reason, - gas_used: final_gas_used, - gas_refunded, - logs: vec![], // todo: logs - output, - }, - SuccessOrHalt::Revert => RevmExecutionResult::Revert { - gas_used: final_gas_used, - output: output.into_data(), - }, - SuccessOrHalt::Halt(reason) => RevmExecutionResult::Halt { - reason, - gas_used: final_gas_used, - }, - // Only two internal return flags. - SuccessOrHalt::FatalExternalError - | SuccessOrHalt::InternalContinue - | SuccessOrHalt::InternalCallOrCreate => { - panic!("Internal return flags should remain internal {instruction_result:?}") - } - }; - - Ok(result) - } } diff --git a/src/executor.rs b/src/executor.rs new file mode 100644 index 0000000..16ce265 --- /dev/null +++ b/src/executor.rs @@ -0,0 +1,110 @@ +use std::mem::replace; +use pyo3::PyResult; +use revm::{Context, Evm, EvmContext, FrameOrResult, FrameResult}; +use revm::primitives::{ExecutionResult}; +use revm::primitives::TransactTo; +use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; +use crate::database::DB; +use crate::utils::pyerr; + +pub(crate) fn evm_call(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { + evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; + let initial_gas_spend = evm + .handler + .validation() + .initial_tx_gas(&evm.context.evm.env) + .map_err(pyerr)?; + evm.handler + .validation() + .tx_against_state(&mut evm.context) + .map_err(pyerr)?; + + let ctx = &mut evm.context; + let pre_exec = evm.handler.pre_execution(); + + // load access list and beneficiary if needed. + pre_exec.load_accounts(ctx).map_err(pyerr)?; + + // load precompiles + ctx.evm.set_precompiles(pre_exec.load_precompiles()); + + // deduce caller balance with its limit. + pre_exec.deduct_caller(ctx).map_err(pyerr)?; + + let gas_limit = ctx.evm.env.tx.gas_limit - initial_gas_spend; + + let exec = evm.handler.execution(); + // call inner handling of call/create + let first_frame_or_result = match ctx.evm.env.tx.transact_to { + TransactTo::Call(_) => exec.call( + ctx, + CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + ).map_err(pyerr)?, + TransactTo::Create(_) => exec.create( + ctx, + CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + ).map_err(pyerr)?, + }; + + // Starts the main running loop. + let mut result = match first_frame_or_result { + FrameOrResult::Frame(first_frame) => evm.start_the_loop(first_frame).map_err(pyerr)?, + FrameOrResult::Result(result) => result, + }; + + let ctx = &mut evm.context; + + // handle output of call/create calls. + evm.handler + .execution() + .last_frame_return(ctx, &mut result) + .map_err(pyerr)?; + + let post_exec = evm.handler.post_execution(); + // Reimburse the caller + post_exec.reimburse_caller(ctx, result.gas()).map_err(pyerr)?; + // Reward beneficiary + post_exec.reward_beneficiary(ctx, result.gas()).map_err(pyerr)?; + // Returns output of transaction. + Ok((output(ctx, result)?, evm.context.evm)) +} + +/// Main return handle, returns the output of the transaction. +#[inline] +fn output( + context: &mut Context, + result: FrameResult, +) -> PyResult { + replace(&mut context.evm.error, Ok(())).map_err(pyerr)?; + // used gas with refund calculated. + let gas_refunded = result.gas().refunded() as u64; + let final_gas_used = result.gas().spend() - gas_refunded; + let output = result.output(); + let instruction_result = result.into_interpreter_result(); + + let result = match instruction_result.result.into() { + SuccessOrHalt::Success(reason) => ExecutionResult::Success { + reason, + gas_used: final_gas_used, + gas_refunded, + logs: vec![], // todo: logs + output, + }, + SuccessOrHalt::Revert => ExecutionResult::Revert { + gas_used: final_gas_used, + output: output.into_data(), + }, + SuccessOrHalt::Halt(reason) => ExecutionResult::Halt { + reason, + gas_used: final_gas_used, + }, + // Only two internal return flags. + SuccessOrHalt::FatalExternalError + | SuccessOrHalt::InternalContinue + | SuccessOrHalt::InternalCallOrCreate => { + panic!("Internal return flags should remain internal {instruction_result:?}") + } + }; + + Ok(result) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 2762b23..9daff0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ mod utils; mod empty_db_wrapper; mod database; mod pystdout; +mod executor; #[pymodule] fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { diff --git a/src/utils.rs b/src/utils.rs index c353522..e038fa5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,10 +1,8 @@ use pyo3::{exceptions::PyTypeError, prelude::*}; -use revm::primitives::{Address, State, HashMap as RevmHashMap}; +use revm::primitives::{Address, HashMap as RevmHashMap}; use std::fmt::Debug; use pyo3::exceptions::PyRuntimeError; -use std::collections::HashMap; use revm::db::DbAccount; -use crate::AccountInfo; use crate::types::PyDB; pub(crate) fn addr(s: &str) -> Result { @@ -19,12 +17,6 @@ pub(crate) fn addr_or_zero(s: Option<&str>) -> Result { } } -pub(crate) fn pydict(res: State) -> HashMap { - res.iter().map( - |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) - ).collect() -} - /// Convert a Rust error into a Python error. pub(crate) fn pyerr(err: T) -> PyErr { PyRuntimeError::new_err(format!("{:?}", err)) From cfd0e468987704bee04c27e4e785bf159e9e33f3 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 20 Mar 2024 21:07:31 +0100 Subject: [PATCH 16/33] Rename and move --- README.md | 2 +- bench/snailtracer/snailtracer.py | 2 +- pyrevm.pyi | 2 +- pytest/test.py | 16 ++++++------ src/evm.rs | 43 ++++++-------------------------- src/executor.rs | 36 ++++++++++++++++++++++++-- 6 files changed, 52 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 03a563a..eaa6b96 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ vb_before = evm.basic(address) assert vb_before != 0 # Execute the tx -evm.call_raw( +evm.message_call( caller=address, to=address2, value=10000 diff --git a/bench/snailtracer/snailtracer.py b/bench/snailtracer/snailtracer.py index c696bc5..cf20661 100644 --- a/bench/snailtracer/snailtracer.py +++ b/bench/snailtracer/snailtracer.py @@ -35,7 +35,7 @@ def _benchmark( warmup_runs: int = 2, ) -> None: def bench() -> None: - evm.call_raw( + evm.message_call( caller=caller_address, to=contract_address, data=call_data, diff --git a/pyrevm.pyi b/pyrevm.pyi index 80c9fe3..aa6e155 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -140,7 +140,7 @@ class EVM: :param info: The account info. """ - def call_raw( + def message_call( self: "EVM", caller: str, to: str, diff --git a/pytest/test.py b/pytest/test.py index 1ffd42f..773ead9 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -48,7 +48,7 @@ def test_revm_fork(): assert vb_before is not None # Execute the tx - evm.call_raw( + evm.message_call( caller=address, to=address2, value=10000 @@ -107,14 +107,14 @@ def test_balances_fork(): @pytest.mark.parametrize("kwargs", KWARG_CASES) -def test_call_raw(kwargs): +def test_message_call(kwargs): evm = EVM(**kwargs) info = AccountInfo(code=load_contract_bin("full_math.bin")) evm.insert_account_info(address, info) assert evm.basic(address).code == info.code # mulDiv() -> 64 * 8 / 2 - result = evm.call_raw( + result = evm.message_call( caller=address2, to=address, calldata=bytes.fromhex( @@ -133,7 +133,7 @@ def test_call_committing(kwargs): ) # mulDivRoundingUp() -> 64 * 8 / 3 - result = evm.call_raw( + result = evm.message_call( caller=address2, to=address, calldata=bytes.fromhex( @@ -150,7 +150,7 @@ def test_call_revert(): evm.set_balance(address2, amount) snapshot = evm.snapshot() - evm.call_raw( + evm.message_call( caller=address2, to=address, value=amount, @@ -169,7 +169,7 @@ def test_call_empty_result(kwargs): evm.set_balance(address2, 10000) - deposit = evm.call_raw( + deposit = evm.message_call( caller=address2, to=address, value=10000, @@ -178,7 +178,7 @@ def test_call_empty_result(kwargs): assert deposit == [] - balance = evm.call_raw( + balance = evm.message_call( caller=address2, to=address, calldata=bytes.fromhex("70a08231" + encode_address(address2)), @@ -192,7 +192,7 @@ def test_tracing(capsys): evm = EVM(tracing=True) evm.insert_account_info(address, AccountInfo(code=load_contract_bin("weth_9.bin"))) evm.set_balance(address2, 10000) - evm.call_raw( + evm.message_call( caller=address2, to=address, value=10000, diff --git a/src/evm.rs b/src/evm.rs index 363c4e1..7d3889f 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -4,8 +4,7 @@ use std::mem::replace; use pyo3::{pyclass, pymethods, PyResult}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; -use revm::{Context, ContextWithHandlerCfg, Database, Evm, EvmContext, inspector_handle_register, JournalCheckpoint as RevmCheckpoint, primitives::U256}; -use revm::inspectors::TracerEip3155; +use revm::{Database, Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::precompile::{Address, Bytes}; use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; use RevmExecutionResult::Success; @@ -13,8 +12,7 @@ use tracing::trace; use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; use crate::database::DB; -use crate::executor::evm_call; -use crate::pystdout::PySysStdout; +use crate::executor::call_evm; use crate::types::{PyBytes, PyDB}; use crate::utils::to_hashmap; @@ -147,7 +145,7 @@ impl EVM { } #[pyo3(signature = (caller, to, calldata = None, value = None))] - pub fn call_raw( + pub fn message_call( &mut self, caller: &str, to: &str, @@ -155,7 +153,7 @@ impl EVM { value: Option, ) -> PyResult { let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - match self.call_raw_with_env(env) + match self.call_with_env(env) { Ok(data) => Ok(data.to_vec()), Err(e) => Err(e), @@ -271,7 +269,7 @@ impl EVM { } } - fn call_raw_with_env(&mut self, env: RevmEnv) -> PyResult { + fn call_with_env(&mut self, env: RevmEnv) -> PyResult { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), "Expect call transaction" @@ -288,38 +286,11 @@ impl EVM { fn run_env(&mut self, env: RevmEnv) -> PyResult { self.context.env = Box::new(env); - - // temporarily take the context out of the EVM instance let evm_context: EvmContext = replace(&mut self.context, EvmContext::new(DB::new_memory())); - - let (result, evm_context) = if self.tracing { - let tracer = TracerEip3155::new(Box::new(PySysStdout {}), true); - let evm = Evm::builder() - .with_context_with_handler_cfg(ContextWithHandlerCfg { - cfg: self.handler_cfg, - context: Context { - evm: evm_context, - external: tracer, - }, - }) - .append_handler_register(inspector_handle_register) - .build(); - evm_call(evm) - } else { - let evm = Evm::builder() - .with_context_with_handler_cfg(ContextWithHandlerCfg { - cfg: self.handler_cfg, - context: Context { - evm: evm_context, - external: (), - }, - }) - .build(); - - evm_call(evm) - }?; + let (result, evm_context) = call_evm(evm_context, self.handler_cfg, self.tracing)?; self.context = evm_context; self.result = Some(result.clone()); Ok(result) } + } diff --git a/src/executor.rs b/src/executor.rs index 16ce265..148340b 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,13 +1,45 @@ use std::mem::replace; use pyo3::PyResult; -use revm::{Context, Evm, EvmContext, FrameOrResult, FrameResult}; +use revm::{Context, ContextWithHandlerCfg, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register}; +use revm::inspectors::TracerEip3155; use revm::primitives::{ExecutionResult}; use revm::primitives::TransactTo; use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; +use revm_interpreter::primitives::HandlerCfg; use crate::database::DB; use crate::utils::pyerr; -pub(crate) fn evm_call(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { +pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tracing: bool) -> PyResult<(ExecutionResult, EvmContext)> { + let (result, evm_context) = if tracing { + let tracer = TracerEip3155::new(Box::new(crate::pystdout::PySysStdout {}), true); + let evm = Evm::builder() + .with_context_with_handler_cfg(ContextWithHandlerCfg { + cfg: handler_cfg, + context: Context { + evm: evm_context, + external: tracer, + }, + }) + .append_handler_register(inspector_handle_register) + .build(); + evm_call(evm) + } else { + let evm = Evm::builder() + .with_context_with_handler_cfg(ContextWithHandlerCfg { + cfg: handler_cfg, + context: Context { + evm: evm_context, + external: (), + }, + }) + .build(); + + evm_call(evm) + }?; + Ok((result, evm_context)) +} + +fn evm_call(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm .handler From 84c17435a37c8daa3db6b51b4dc03e4122f94ea6 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Thu, 21 Mar 2024 12:15:31 +0100 Subject: [PATCH 17/33] Expose actual PyBytes + check get_code return --- pyrevm.pyi | 22 ++++++-- pytest/contracts/blueprint.bin | 1 + pytest/test.py | 26 ++++++++-- src/evm.rs | 94 +++++++++++++++++++++++----------- src/executor.rs | 12 +++-- src/types/evm_env.rs | 6 +-- src/types/execution_result.rs | 38 ++------------ src/types/info.rs | 5 +- src/types/mod.rs | 2 +- src/utils.rs | 13 ++--- 10 files changed, 125 insertions(+), 94 deletions(-) create mode 100644 pytest/contracts/blueprint.bin diff --git a/pyrevm.pyi b/pyrevm.pyi index aa6e155..ae204a4 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -1,4 +1,4 @@ -from typing import Optional, Type, Tuple +from typing import Optional, Type class CfgEnv: @@ -99,9 +99,9 @@ class AccountInfo: @property def nonce(self: "AccountInfo") -> int: ... @property - def code(self: "AccountInfo") -> bytes: ... + def code(self: "AccountInfo") -> Optional[bytes]: ... @property - def code_hash(self: "AccountInfo") -> bytes: ... + def code_hash(self: "AccountInfo") -> Optional[bytes]: ... class EVM: def __new__( @@ -133,6 +133,13 @@ class EVM: :return: The account info. """ + def get_code(self: "EVM", address: str) -> Optional[bytes]: + """ + Returns the code of the given address. + :param address: The address. + :return: The code. + """ + def insert_account_info(self: "EVM", address: str, info: AccountInfo) -> None: """ Inserts the given account info into the state. @@ -184,7 +191,7 @@ class EVM: :param balance: The balance. """ - def storage(self: "EVM", address: str, index: int) -> int: + def storage(self: "EVM", address: str, index: int) -> Optional[int]: """ Returns the storage value of the given address at the given index. :param address: The address. @@ -192,6 +199,13 @@ class EVM: :return: The storage value. """ + def block_hash(self: "EVM", number: int) -> Optional[bytes]: + """ + Returns the block hash of the given number. + :param number: The number. + :return: The block hash. + """ + @property def env(self: "EVM") -> Env: """ Get the environment. """ diff --git a/pytest/contracts/blueprint.bin b/pytest/contracts/blueprint.bin new file mode 100644 index 0000000..9a25ad9 --- /dev/null +++ b/pytest/contracts/blueprint.bin @@ -0,0 +1 @@ +61002761000f6000396100276000f35f3560e01c63c2985578811861001f573461002357607b60405260206040f35b5f5ffd5b5f80fd8418278000a16576797065728300030b0012 \ No newline at end of file diff --git a/pytest/test.py b/pytest/test.py index 773ead9..45eab59 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -70,12 +70,12 @@ def test_deploy(): assert vb_before.nonce == 0 # Deploy the contract - deployed_at = evm.deploy( - deployer=address, - code=bytes.fromhex("6060"), - ) + code = bytes.fromhex("6060") + deployed_at = evm.deploy(address, code) assert deployed_at == "0x3e4ea2156166390f880071d94458efb098473311" + deployed_code = evm.get_code(deployed_at) + assert deployed_code == code def test_balances(): @@ -176,7 +176,7 @@ def test_call_empty_result(kwargs): calldata=bytes.fromhex("d0e30db0"), ) - assert deposit == [] + assert deposit == b"" balance = evm.message_call( caller=address2, @@ -206,3 +206,19 @@ def test_tracing(capsys): 'pass': True, 'stateRoot': '0x0000000000000000000000000000000000000000000000000000000000000000'} == traces[-1] assert len(traces) == 128 + +def test_blueprint(): + evm = EVM() + # bytecode based on vyper `@external def foo() -> uint256: return 123` + bytecode = load_contract_bin("blueprint.bin") + + bytecode = b"\xFE\x71\x00" + bytecode + bytecode_len = len(bytecode) + bytecode_len_hex = hex(bytecode_len)[2:].rjust(4, "0") + + # prepend a quick deploy preamble + deploy_preamble = bytes.fromhex("61" + bytecode_len_hex + "3d81600a3d39f3") + deploy_bytecode = deploy_preamble + bytecode + + deployer_address = evm.deploy(address, deploy_bytecode) + assert evm.basic(address).code == deploy_bytecode diff --git a/src/evm.rs b/src/evm.rs index 7d3889f..c976bb7 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -2,9 +2,10 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::mem::replace; -use pyo3::{pyclass, pymethods, PyResult}; +use pyo3::{pyclass, pymethods, PyObject, PyResult, Python}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; -use revm::{Database, Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256}; +use pyo3::types::PyBytes; +use revm::{Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::precompile::{Address, Bytes}; use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; use RevmExecutionResult::Success; @@ -13,8 +14,7 @@ use tracing::trace; use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; use crate::database::DB; use crate::executor::call_evm; -use crate::types::{PyBytes, PyDB}; -use crate::utils::to_hashmap; +use crate::types::{PyByteVec, PyDB}; #[derive(Debug)] #[pyclass] @@ -104,14 +104,27 @@ impl EVM { Ok(account.info.clone().into()) } + fn get_code(&mut self, address: &str, py: Python<'_>) -> PyResult> { + let (code, _) = self.context.code(addr(address)?).map_err(pyerr)?; + if code.is_empty() { + return Ok(None); + } + Ok(Some(PyBytes::new(py, &code.bytecode.to_vec()).into())) + } + /// Get storage value of address at index. - fn storage(&mut self, address: &str, index: U256) -> PyResult { - Ok(self.context.db.storage(addr(address)?, index)?) + fn storage(&mut self, address: &str, index: U256) -> PyResult> { + let (account, _) = self.context.load_account(addr(address)?).map_err(pyerr)?; + Ok(account.storage.get(&index).map(|s| s.present_value)) } /// Get block hash by block number. - fn block_hash(&mut self, number: U256) -> PyResult { - Ok(self.context.block_hash(number).map_err(pyerr)?.to_vec()) + fn block_hash(&mut self, number: U256, py: Python<'_>) -> PyResult> { + let bytes = self.context.block_hash(number).map_err(pyerr)?; + if bytes.is_empty() { + return Ok(None); + } + Ok(Some(PyBytes::new(py, &bytes.to_vec()).into())) } /// Inserts the provided account information in the database at the specified address. @@ -120,7 +133,13 @@ impl EVM { address: &str, info: AccountInfo, ) -> PyResult<()> { - self.context.db.insert_account_info(addr(address)?, info.clone().into()); + let target = addr(address)?; + match self.context.journaled_state.state.get_mut(&target) { + // account is cold, just insert into the DB, so it's retrieved next time + None => self.context.db.insert_account_info(target, info.into()), + // just replace the account info + Some(acc) => acc.info = info.into(), + } Ok(()) } @@ -132,7 +151,6 @@ impl EVM { account.info.balance = balance; account.clone() }; - self.context.db.insert_account_info(address_, account.info.clone()); self.context.journaled_state.state.insert(address_, account); self.context.journaled_state.touch(&address_); Ok(()) @@ -149,13 +167,14 @@ impl EVM { &mut self, caller: &str, to: &str, - calldata: Option, + calldata: Option, value: Option, - ) -> PyResult { + py: Python<'_>, + ) -> PyResult { let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); match self.call_with_env(env) { - Ok(data) => Ok(data.to_vec()), + Ok(data) => Ok(PyBytes::new(py, &data.to_vec()).into()), Err(e) => Err(e), } } @@ -164,7 +183,7 @@ impl EVM { fn deploy( &mut self, deployer: &str, - code: Option, + code: Option, value: Option, _abi: Option<&str>, ) -> PyResult { @@ -200,13 +219,29 @@ impl EVM { fn journal_depth(&self) -> usize { self.context.journaled_state.depth } + #[getter] fn journal_len(&self) -> usize { self.context.journaled_state.journal.len() } - fn get_accounts(&self) -> PyDB { - to_hashmap(self.context.db.get_accounts()) + #[getter] + fn journal_str(&self) -> String { + format!("{:?}", self.context.journaled_state) + } + + #[getter] + fn db_accounts(&self) -> PyDB { + self.context.db.get_accounts().iter().map( + |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) + ).collect() + } + + #[getter] + fn journal_state(&self) -> PyDB { + self.context.journaled_state.state.iter().map( + |(address, acc)| (address.to_string(), acc.info.clone().into()) + ).collect() } } @@ -258,14 +293,13 @@ impl EVM { let result = self.run_env(env)?; - match &result { - Success { output, .. } => { - match output { - Output::Create(_, address) => Ok(address.unwrap()), - _ => Err(pyerr(output.clone())), - } + if let Success { output, .. } = result { + match output { + Output::Create(_, address) => Ok(address.unwrap()), + _ => Err(pyerr(output.clone())), } - _ => Err(pyerr(result.clone())), + } else { + Err(pyerr(result.clone())) } } @@ -277,14 +311,17 @@ impl EVM { trace!(sender=?env.tx.caller, "deploying contract"); let result = self.run_env(env)?; - match &result { - Success { output, .. } => Ok(output.clone().into_data()), - _ => Err(pyerr(result.clone())), + if let Success { output, .. } = result { + match output { + Output::Call(_) => Ok(output.clone().into_data()), + _ => Err(pyerr(output.clone())), + } + } else { + Err(pyerr(result.clone())) } } - fn run_env(&mut self, env: RevmEnv) -> PyResult - { + fn run_env(&mut self, env: RevmEnv) -> PyResult { self.context.env = Box::new(env); let evm_context: EvmContext = replace(&mut self.context, EvmContext::new(DB::new_memory())); let (result, evm_context) = call_evm(evm_context, self.handler_cfg, self.tracing)?; @@ -292,5 +329,4 @@ impl EVM { self.result = Some(result.clone()); Ok(result) } - } diff --git a/src/executor.rs b/src/executor.rs index 148340b..5ea8d43 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -9,8 +9,9 @@ use revm_interpreter::primitives::HandlerCfg; use crate::database::DB; use crate::utils::pyerr; +/// Calls the EVM with the given context and handler configuration. pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tracing: bool) -> PyResult<(ExecutionResult, EvmContext)> { - let (result, evm_context) = if tracing { + if tracing { let tracer = TracerEip3155::new(Box::new(crate::pystdout::PySysStdout {}), true); let evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { @@ -33,12 +34,11 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra }, }) .build(); - evm_call(evm) - }?; - Ok((result, evm_context)) + } } +/// Calls the given evm. This is originally a copy of revm::Evm::transact, but it calls our own output function fn evm_call(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm @@ -101,7 +101,9 @@ fn evm_call(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmCon Ok((output(ctx, result)?, evm.context.evm)) } -/// Main return handle, returns the output of the transaction. +/// Returns the output of the transaction. +/// This is mostly copied from revm::handler::mainnet::post_execution::output +/// However, we removed the journal finalization to keep the transaction open. #[inline] fn output( context: &mut Context, diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 65d06f9..310955a 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -1,5 +1,5 @@ use crate::utils::{addr, addr_or_zero}; -use pyo3::{exceptions::PyTypeError, pyclass, pymethods, PyResult, types::PyBytes}; +use pyo3::{exceptions::PyTypeError, pyclass, pymethods, PyObject, PyResult, Python, types::{PyBytes}}; use revm::primitives::{BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, CreateScheme, Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256}; #[pyclass] @@ -116,8 +116,8 @@ impl TxEnv { } #[getter] - fn data(&self) -> Vec { - self.0.data.to_vec() + fn data(&self, py: Python<'_>) -> PyObject { + PyBytes::new(py, &self.0.data.to_vec()).into() } #[getter] diff --git a/src/types/execution_result.rs b/src/types/execution_result.rs index 15ed62d..d47f76e 100644 --- a/src/types/execution_result.rs +++ b/src/types/execution_result.rs @@ -1,7 +1,5 @@ use pyo3::{pyclass, pymethods}; -use revm::primitives::{ExecutionResult as RevmExecutionResult, HaltReason, OutOfGasError, SuccessReason}; - -// pub struct Log(RevmLog); +use revm::primitives::ExecutionResult as RevmExecutionResult; #[derive(Debug)] @@ -24,39 +22,9 @@ impl From for ExecutionResult { is_success: result.is_success(), is_halt: result.is_halt(), reason: match result { - RevmExecutionResult::Success { reason, .. } => match reason { - SuccessReason::Stop => String::from("Stop"), - SuccessReason::Return => String::from("Return"), - SuccessReason::SelfDestruct => String::from("SelfDestruct"), - } + RevmExecutionResult::Success { reason, .. } => format!("{:?}", reason), RevmExecutionResult::Revert { .. } => String::from("Revert"), - RevmExecutionResult::Halt { reason, .. } => match reason { - HaltReason::OutOfGas(out_of_gas) => match out_of_gas { - OutOfGasError::Basic => String::from("OutOfGas:Basic"), - OutOfGasError::MemoryLimit => String::from("OutOfGas:MemoryLimit"), - OutOfGasError::Memory => String::from("OutOfGas:Memory"), - OutOfGasError::Precompile => String::from("OutOfGas:Precompile"), - OutOfGasError::InvalidOperand => String::from("OutOfGas:InvalidOperand"), - }, - HaltReason::OpcodeNotFound => String::from("OpcodeNotFound"), - HaltReason::InvalidFEOpcode => String::from("InvalidFEOpcode"), - HaltReason::InvalidJump => String::from("InvalidJump"), - HaltReason::NotActivated => String::from("NotActivated"), - HaltReason::StackUnderflow => String::from("StackUnderflow"), - HaltReason::StackOverflow => String::from("StackOverflow"), - HaltReason::OutOfOffset => String::from("OutOfOffset"), - HaltReason::CreateCollision => String::from("CreateCollision"), - HaltReason::PrecompileError => String::from("PrecompileError"), - HaltReason::NonceOverflow => String::from("NonceOverflow"), - HaltReason::CreateContractSizeLimit => String::from("CreateContractSizeLimit"), - HaltReason::CreateContractStartingWithEF => String::from("CreateContractStartingWithEF"), - HaltReason::CreateInitCodeSizeLimit => String::from("CreateInitCodeSizeLimit"), - HaltReason::OverflowPayment => String::from("OverflowPayment"), - HaltReason::StateChangeDuringStaticCall => String::from("StateChangeDuringStaticCall"), - HaltReason::CallNotAllowedInsideStatic => String::from("CallNotAllowedInsideStatic"), - HaltReason::OutOfFunds => String::from("OutOfFunds"), - HaltReason::CallTooDeep => String::from("CallTooDeep"), - } + RevmExecutionResult::Halt { reason, .. } => format!("{:?}", reason), }, gas_used: match result { RevmExecutionResult::Success { gas_used, .. } => gas_used, diff --git a/src/types/info.rs b/src/types/info.rs index 9ffcca1..df82a26 100644 --- a/src/types/info.rs +++ b/src/types/info.rs @@ -17,14 +17,15 @@ impl AccountInfo { _self.0.nonce } #[getter] - fn code(_self: PyRef<'_, Self>) -> Vec { + fn code(_self: PyRef<'_, Self>, py: Python<'_>) -> Option { _self .0 .code .as_ref() .map(|x| x.bytes().to_vec()) - .unwrap_or_default() + .map(|bytes| PyBytes::new(py, &bytes).into()) } + #[getter] fn code_hash(_self: PyRef<'_, Self>) -> [u8; 32] { _self.0.code_hash.0 diff --git a/src/types/mod.rs b/src/types/mod.rs index 52815c9..84d94d8 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -11,5 +11,5 @@ mod execution_result; mod checkpoint; // In Py03 we use vec to represent bytes -pub(crate) type PyBytes = Vec; +pub(crate) type PyByteVec = Vec; pub(crate) type PyDB = HashMap; diff --git a/src/utils.rs b/src/utils.rs index e038fa5..b14d974 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,8 @@ -use pyo3::{exceptions::PyTypeError, prelude::*}; -use revm::primitives::{Address, HashMap as RevmHashMap}; use std::fmt::Debug; + +use pyo3::{exceptions::PyTypeError, prelude::*}; use pyo3::exceptions::PyRuntimeError; -use revm::db::DbAccount; -use crate::types::PyDB; +use revm::primitives::Address; pub(crate) fn addr(s: &str) -> Result { s.parse::
() @@ -21,9 +20,3 @@ pub(crate) fn addr_or_zero(s: Option<&str>) -> Result { pub(crate) fn pyerr(err: T) -> PyErr { PyRuntimeError::new_err(format!("{:?}", err)) } - -pub(crate) fn to_hashmap(map: &RevmHashMap) -> PyDB { - map.iter().map( - |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) - ).collect() -} From 618ef67d6a2a4541288ea3ac91de17a19b040736 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Thu, 21 Mar 2024 16:55:17 +0100 Subject: [PATCH 18/33] Fix tests --- pytest/contracts/blueprint.bin | 5 ++++- pytest/test.py | 21 +++++++++++++++------ src/evm.rs | 6 +++--- src/executor.rs | 6 +++--- src/types/info.rs | 4 ++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/pytest/contracts/blueprint.bin b/pytest/contracts/blueprint.bin index 9a25ad9..a24c8c0 100644 --- a/pytest/contracts/blueprint.bin +++ b/pytest/contracts/blueprint.bin @@ -1 +1,4 @@ -61002761000f6000396100276000f35f3560e01c63c2985578811861001f573461002357607b60405260206040f35b5f5ffd5b5f80fd8418278000a16576797065728300030b0012 \ No newline at end of file +61002761000f6000396100276000f35f3560e01c63c2985578811861001f573461002357607b60405260206040f35b5f5ffd5b5f80fd8418278000a16576797065728300030b0012 + +only the first line is read in the code. This was generated based on vyper: +@external def foo() -> uint256: return 123 diff --git a/pytest/test.py b/pytest/test.py index 45eab59..0b4a2ca 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -65,17 +65,26 @@ def test_revm_fork(): def test_deploy(): evm = EVM() - vb_before = evm.basic(address) - assert vb_before is not None - assert vb_before.nonce == 0 + account_before = evm.basic(address) + assert account_before is not None + assert account_before.nonce == 0 + assert account_before.code == b"\0" # Deploy the contract - code = bytes.fromhex("6060") + code = load_contract_bin("blueprint.bin") deployed_at = evm.deploy(address, code) assert deployed_at == "0x3e4ea2156166390f880071d94458efb098473311" deployed_code = evm.get_code(deployed_at) - assert deployed_code == code + assert deployed_code.hex().rstrip('0') in code.hex() + assert evm.basic(deployed_at).code.hex() == deployed_code.hex() + + result = evm.message_call( + address, + deployed_at, + calldata=b'\xc2\x98Ux' # ==method_id('foo()') + ) + assert int(result.hex(), 16) == 123 def test_balances(): @@ -221,4 +230,4 @@ def test_blueprint(): deploy_bytecode = deploy_preamble + bytecode deployer_address = evm.deploy(address, deploy_bytecode) - assert evm.basic(address).code == deploy_bytecode + assert evm.basic(deployer_address).code.hex().rstrip('0') in deploy_bytecode.hex() diff --git a/src/evm.rs b/src/evm.rs index c976bb7..b5a3ded 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -190,7 +190,7 @@ impl EVM { let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); match self.deploy_with_env(env) { - Ok(address) => Ok(format!("{:?}", address)), + Ok((_, address)) => Ok(format!("{:?}", address)), Err(e) => Err(e), } } @@ -284,7 +284,7 @@ impl EVM { /// Deploys a contract using the given `env` and commits the new state to the underlying /// database - fn deploy_with_env(&mut self, env: RevmEnv) -> PyResult
{ + fn deploy_with_env(&mut self, env: RevmEnv) -> PyResult<(Bytes, Address)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Create(_)), "Expect create transaction" @@ -295,7 +295,7 @@ impl EVM { if let Success { output, .. } = result { match output { - Output::Create(_, address) => Ok(address.unwrap()), + Output::Create(out, address) => Ok((out, address.unwrap())), _ => Err(pyerr(output.clone())), } } else { diff --git a/src/executor.rs b/src/executor.rs index 5ea8d43..44df2e9 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -23,7 +23,7 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra }) .append_handler_register(inspector_handle_register) .build(); - evm_call(evm) + run_evm(evm) } else { let evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { @@ -34,12 +34,12 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra }, }) .build(); - evm_call(evm) + run_evm(evm) } } /// Calls the given evm. This is originally a copy of revm::Evm::transact, but it calls our own output function -fn evm_call(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { +fn run_evm(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm .handler diff --git a/src/types/info.rs b/src/types/info.rs index df82a26..f3c1127 100644 --- a/src/types/info.rs +++ b/src/types/info.rs @@ -27,8 +27,8 @@ impl AccountInfo { } #[getter] - fn code_hash(_self: PyRef<'_, Self>) -> [u8; 32] { - _self.0.code_hash.0 + fn code_hash(_self: PyRef<'_, Self>, py: Python<'_>) -> PyObject { + PyBytes::new(py, &_self.0.code_hash.0).into() } #[new] From 0dce9d83d44baa8f2e2c074f9264bad53b0c963a Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Thu, 21 Mar 2024 16:58:45 +0100 Subject: [PATCH 19/33] Review comment --- src/database.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/database.rs b/src/database.rs index d3b7252..d25d3c6 100644 --- a/src/database.rs +++ b/src/database.rs @@ -22,13 +22,13 @@ type ForkDB = CacheDB>>; /// without needing dynamic lifetime and generic parameters (unsupported in PyO3) #[derive(Clone, Debug)] pub(crate) enum DB { - Memory(Box), - Fork(Box), + Memory(MemDB), + Fork(ForkDB), } impl DB { pub(crate) fn new_memory() -> Self { - DB::Memory(Box::new(MemDB::new(EmptyDBWrapper::default()))) + DB::Memory(MemDB::new(EmptyDBWrapper::default())) } pub(crate) fn new_fork( @@ -39,7 +39,7 @@ impl DB { let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; let db = EthersDB::new(Arc::new(provider), block).unwrap(); // todo: do we need to get the blockEnv from the client? - Ok(DB::Fork(Box::new(CacheDB::new(db)))) + Ok(DB::Fork(CacheDB::new(db))) } /// Insert account info but not override storage From f6aa77114e5d45c6ecfd63b262e1061486469d09 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Fri, 22 Mar 2024 09:38:33 +0100 Subject: [PATCH 20/33] Documentation --- README.md | 43 ++++++++++++++++++++++++++++++++++++------- pyrevm.pyi | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ pytest/test.py | 5 +++-- 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index eaa6b96..b4e0236 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Here we show how you can fork from Ethereum mainnet and simulate a transaction from `vitalik.eth`. ```python -from pyrevm import * +from pyrevm import EVM, Env, BlockEnv address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" # vitalik.eth address2 = "0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" @@ -33,9 +33,9 @@ evm = EVM( tracing=True, # can configure the environment env=Env( - block=BlockEnv(timestamp=100 - )) -); + block=BlockEnv(timestamp=100) + ) +) vb_before = evm.basic(address) assert vb_before != 0 @@ -46,19 +46,48 @@ evm.message_call( to=address2, value=10000 # data -); +) assert vb_before != evm.basic(address) assert evm.basic(address2).balance == 10000 ``` +### Tracing +There is also support for tracing: +```python +from pyrevm import EVM + +EVM(tracing=True) +``` + +### Transactions + +There is support for checkpoints: + +```python +from pyrevm import EVM + +evm = EVM() +checkpoint = evm.snapshot() +evm.message_call( + caller=..., + to=..., + value=..., +) +evm.revert(checkpoint) # or: evm.commit() to clear all checkpoints +``` + +**Note**: in contrast to the Rust library, the Python library does not automatically commit to database. + +See more usage examples in the [pytests](./pytest/test.py). + ## Develop We use Poetry for virtual environment management and [Maturin](https://github.com/PyO3/maturin) as our Rust <> Python FFI build system. The Rust bindings are auto-generated from the macros provided by [PyO3](https://pyo3.rs/v0.17.1/). -To build the library, run `poetry run maturin develop` +To build the library, run `make build`. To run the tests, run `make test`. -Note: If building for production, do not forget the `--release` flag, else performance will be degraded. +Note: If building for production, use `make build-prod`, else performance will be degraded. ## Benchmarks diff --git a/pyrevm.pyi b/pyrevm.pyi index ae204a4..4ff341e 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -103,6 +103,28 @@ class AccountInfo: @property def code_hash(self: "AccountInfo") -> Optional[bytes]: ... + +class ExecutionResult: + def __new__( + cls: Type["ExecutionResult"], + is_success: bool, + is_halt: bool, + reason: str, + gas_used: int, + gas_refunded: int, + ) -> "ExecutionResult": ... + @property + def is_success(self) -> bool: ... + @property + def is_halt(self) -> bool: ... + @property + def reason(self) -> str: ... + @property + def gas_used(self) -> int: ... + @property + def gas_refunded(self) -> int: ... + + class EVM: def __new__( cls: Type["EVM"], @@ -213,3 +235,31 @@ class EVM: @property def tracing(self: "EVM") -> bool: """ Whether tracing is enabled. """ + + @property + def result(self: "EVM") -> Optional[ExecutionResult]: + """ The result of the execution. """ + + @property + def checkpoint_ids(self: "EVM") -> set[JournalCheckpoint]: + """ The checkpoint IDs. """ + + @property + def journal_depth(self: "EVM") -> int: + """ The journal depth. """ + + @property + def journal_len(self: "EVM") -> int: + """ The journal length. """ + + @property + def journal_str(self: "EVM") -> str: + """ The journal string. """ + + @property + def db_accounts(self: "EVM") -> dict[str, AccountInfo]: + """ The accounts in the database. """ + + @property + def journal_state(self: "EVM") -> dict[str, AccountInfo]: + """ The state in the journal. """ diff --git a/pytest/test.py b/pytest/test.py index 0b4a2ca..7c1a16e 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -158,7 +158,7 @@ def test_call_revert(): amount = 10000 evm.set_balance(address2, amount) - snapshot = evm.snapshot() + checkpoint = evm.snapshot() evm.message_call( caller=address2, to=address, @@ -166,7 +166,7 @@ def test_call_revert(): ) assert evm.get_balance(address) == amount - evm.revert(snapshot) + evm.revert(checkpoint) assert evm.get_balance(address) == 0 assert evm.get_balance(address2) == amount @@ -216,6 +216,7 @@ def test_tracing(capsys): 'stateRoot': '0x0000000000000000000000000000000000000000000000000000000000000000'} == traces[-1] assert len(traces) == 128 + def test_blueprint(): evm = EVM() # bytecode based on vyper `@external def foo() -> uint256: return 123` From 7ace79aa211d662cf2e50d8a3a104ac4945fd221 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Fri, 22 Mar 2024 10:58:48 +0100 Subject: [PATCH 21/33] Add `create2`, `gas` and `is_static` support --- pyrevm.pyi | 7 +++++++ src/evm.rs | 32 +++++++++++++++++++------------- src/executor.rs | 16 +++++++++++----- src/types/evm_env.rs | 18 ++++++++++++++---- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index 4ff341e..f570659 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -43,6 +43,7 @@ class TxEnv: data: Optional[bytes] = None, chain_id: Optional[int] = None, nonce: Optional[int] = None, + salt: Optional[int] = None, ) -> "TxEnv": ... @property @@ -190,12 +191,18 @@ class EVM: deployer: str, code: bytes, value: Optional[int] = None, + gas: Optional[int] = None, + is_static = False, + _abi: Optional[list[dict]] = None ) -> str: """ Deploys the given code. :param deployer: The address of the deployer. :param code: The code. :param value: The value. + :param gas: The gas. + :param is_static: Whether the deployment is static (i.e. does not change the state). + :param _abi: The ABI. :return: The address of the deployed contract. """ diff --git a/src/evm.rs b/src/evm.rs index b5a3ded..de62e9c 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -162,17 +162,19 @@ impl EVM { Ok(balance) } - #[pyo3(signature = (caller, to, calldata = None, value = None))] + #[pyo3(signature = (caller, to, calldata = None, value = None, gas = None, is_static = false))] pub fn message_call( &mut self, caller: &str, to: &str, calldata: Option, value: Option, + gas: Option, + is_static: bool, py: Python<'_>, ) -> PyResult { - let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into()); - match self.call_with_env(env) + let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into(), gas); + match self.call_with_env(env, is_static) { Ok(data) => Ok(PyBytes::new(py, &data.to_vec()).into()), Err(e) => Err(e), @@ -180,15 +182,18 @@ impl EVM { } /// Deploy a contract with the given code. + #[pyo3(signature = (deployer, code, value = None, gas = None, is_static = false, _abi = None))] fn deploy( &mut self, deployer: &str, - code: Option, + code: PyByteVec, value: Option, + gas: Option, + is_static: bool, _abi: Option<&str>, ) -> PyResult { - let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.unwrap_or_default().into(), value.unwrap_or_default()); - match self.deploy_with_env(env) + let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.into(), value.unwrap_or_default(), gas); + match self.deploy_with_env(env, is_static) { Ok((_, address)) => Ok(format!("{:?}", address)), Err(e) => Err(e), @@ -257,6 +262,7 @@ impl EVM { transact_to: TransactTo, data: Bytes, value: U256, + gas: Option, ) -> RevmEnv { RevmEnv { cfg: self.context.env.cfg.clone(), @@ -276,7 +282,7 @@ impl EVM { // As above, we set the gas price to 0. gas_price: U256::ZERO, gas_priority_fee: None, - gas_limit: self.gas_limit.to(), + gas_limit: gas.unwrap_or(self.gas_limit).to(), ..self.context.env.tx.clone() }, } @@ -284,14 +290,14 @@ impl EVM { /// Deploys a contract using the given `env` and commits the new state to the underlying /// database - fn deploy_with_env(&mut self, env: RevmEnv) -> PyResult<(Bytes, Address)> { + fn deploy_with_env(&mut self, env: RevmEnv, is_static: bool) -> PyResult<(Bytes, Address)> { debug_assert!( matches!(env.tx.transact_to, TransactTo::Create(_)), "Expect create transaction" ); trace!(sender=?env.tx.caller, "deploying contract"); - let result = self.run_env(env)?; + let result = self.run_env(env, is_static)?; if let Success { output, .. } = result { match output { @@ -303,14 +309,14 @@ impl EVM { } } - fn call_with_env(&mut self, env: RevmEnv) -> PyResult { + fn call_with_env(&mut self, env: RevmEnv, is_static: bool) -> PyResult { debug_assert!( matches!(env.tx.transact_to, TransactTo::Call(_)), "Expect call transaction" ); trace!(sender=?env.tx.caller, "deploying contract"); - let result = self.run_env(env)?; + let result = self.run_env(env, is_static)?; if let Success { output, .. } = result { match output { Output::Call(_) => Ok(output.clone().into_data()), @@ -321,10 +327,10 @@ impl EVM { } } - fn run_env(&mut self, env: RevmEnv) -> PyResult { + fn run_env(&mut self, env: RevmEnv, is_static: bool) -> PyResult { self.context.env = Box::new(env); let evm_context: EvmContext = replace(&mut self.context, EvmContext::new(DB::new_memory())); - let (result, evm_context) = call_evm(evm_context, self.handler_cfg, self.tracing)?; + let (result, evm_context) = call_evm(evm_context, self.handler_cfg, self.tracing, is_static)?; self.context = evm_context; self.result = Some(result.clone()); Ok(result) diff --git a/src/executor.rs b/src/executor.rs index 44df2e9..3f5cc83 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -10,7 +10,7 @@ use crate::database::DB; use crate::utils::pyerr; /// Calls the EVM with the given context and handler configuration. -pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tracing: bool) -> PyResult<(ExecutionResult, EvmContext)> { +pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tracing: bool, is_static: bool) -> PyResult<(ExecutionResult, EvmContext)> { if tracing { let tracer = TracerEip3155::new(Box::new(crate::pystdout::PySysStdout {}), true); let evm = Evm::builder() @@ -23,7 +23,7 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra }) .append_handler_register(inspector_handle_register) .build(); - run_evm(evm) + run_evm(evm, is_static) } else { let evm = Evm::builder() .with_context_with_handler_cfg(ContextWithHandlerCfg { @@ -34,12 +34,12 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra }, }) .build(); - run_evm(evm) + run_evm(evm, is_static) } } /// Calls the given evm. This is originally a copy of revm::Evm::transact, but it calls our own output function -fn run_evm(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmContext)> { +fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(ExecutionResult, EvmContext)> { evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm .handler @@ -70,7 +70,7 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmCont let first_frame_or_result = match ctx.evm.env.tx.transact_to { TransactTo::Call(_) => exec.call( ctx, - CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + call_inputs(&ctx, gas_limit, is_static), ).map_err(pyerr)?, TransactTo::Create(_) => exec.create( ctx, @@ -101,6 +101,12 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>) -> PyResult<(ExecutionResult, EvmCont Ok((output(ctx, result)?, evm.context.evm)) } +fn call_inputs(ctx: &&mut Context, gas_limit: u64, is_static: bool) -> Box { + let mut inputs = CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(); + inputs.is_static = is_static; + inputs +} + /// Returns the output of the transaction. /// This is mostly copied from revm::handler::mainnet::post_execution::output /// However, we removed the journal finalization to keep the transaction open. diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 310955a..42bc88a 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -1,6 +1,6 @@ use crate::utils::{addr, addr_or_zero}; use pyo3::{exceptions::PyTypeError, pyclass, pymethods, PyObject, PyResult, Python, types::{PyBytes}}; -use revm::primitives::{BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, CreateScheme, Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256}; +use revm::primitives::{BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256, CreateScheme}; #[pyclass] #[derive(Clone, Debug, Default)] @@ -62,6 +62,7 @@ impl TxEnv { data: Option>, chain_id: Option, nonce: Option, + salt: Option, ) -> PyResult { Ok(TxEnv(RevmTxEnv { caller: addr_or_zero(caller)?, @@ -69,9 +70,8 @@ impl TxEnv { gas_price: gas_price.unwrap_or_default(), gas_priority_fee: gas_priority_fee.map(Into::into), transact_to: match to { - Some(inner) => TransactTo::Call(addr(inner)?), - // TODO: Figure out how to integrate CREATE2 here - None => TransactTo::Create(CreateScheme::Create), + Some(inner) => TransactTo::call(addr(inner)?), + None => if salt.is_some() { TransactTo::create2(salt.unwrap()) } else { TransactTo::create() }, }, value: value.unwrap_or_default(), data: data.unwrap_or_default().into(), @@ -129,6 +129,16 @@ impl TxEnv { fn nonce(&self) -> Option { self.0.nonce } + + #[getter] + fn salt(&self) -> Option { + if let TransactTo::Create(scheme) = self.0.transact_to { + if let CreateScheme::Create2 { salt } = scheme { + return Some(salt); + } + } + None + } } impl From for RevmTxEnv { From 5bbc43d68046969fc598dced4d10256a4abd7d24 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Fri, 22 Mar 2024 11:06:24 +0100 Subject: [PATCH 22/33] Fix stub --- pyrevm.pyi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyrevm.pyi b/pyrevm.pyi index f570659..e5a0471 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -176,6 +176,8 @@ class EVM: to: str, calldata: Optional[bytes] = None, value: Optional[int] = None, + gas: Optional[int] = None, + is_static = False, ) -> bytes: """ Processes a raw call, without committing the result to the state. @@ -183,6 +185,8 @@ class EVM: :param to: The address of the callee. :param calldata: The calldata. :param value: The value. + :param gas: The gas. + :param is_static: Whether the call is static (i.e. does not change the state). :return: The return data and a list of changes to the state. """ From e77c7767e6086cda88b674f3b203542207cc7577 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Mon, 25 Mar 2024 09:36:29 +0100 Subject: [PATCH 23/33] Expose logs --- pyrevm.pyi | 18 +++++++++++++ src/evm.rs | 6 +---- src/executor.rs | 11 ++++++-- src/lib.rs | 4 ++- src/types/execution_result.rs | 51 ++++++++++++++++++++++++++++++++--- 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index e5a0471..ea54e5c 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -124,6 +124,8 @@ class ExecutionResult: def gas_used(self) -> int: ... @property def gas_refunded(self) -> int: ... + @property + def logs(self) -> list["Log"]: ... class EVM: @@ -247,6 +249,10 @@ class EVM: def tracing(self: "EVM") -> bool: """ Whether tracing is enabled. """ + @tracing.setter + def set_tracing(self: "EVM", value: bool) -> None: + """ Set whether tracing is enabled. """ + @property def result(self: "EVM") -> Optional[ExecutionResult]: """ The result of the execution. """ @@ -274,3 +280,15 @@ class EVM: @property def journal_state(self: "EVM") -> dict[str, AccountInfo]: """ The state in the journal. """ + + +class Log: + @property + def address(self) -> str: ... + + @property + def topics(self) -> list[str]: ... + + @property + def data(self) -> tuple[list[bytes], bytes]: + """ :return: A tuple with a list of topics and the log data. """ diff --git a/src/evm.rs b/src/evm.rs index de62e9c..1f8287e 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -31,6 +31,7 @@ pub struct EVM { gas_limit: U256, /// whether to trace the execution to stdout + #[pyo3(get, set)] tracing: bool, /// Checkpoints for reverting state @@ -205,11 +206,6 @@ impl EVM { (*self.context.env).clone().into() } - #[getter] - fn tracing(&self) -> bool { - self.tracing - } - #[getter] fn result(&self) -> Option { self.result.clone().map(|r| r.into()) diff --git a/src/executor.rs b/src/executor.rs index 3f5cc83..6392404 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -2,6 +2,7 @@ use std::mem::replace; use pyo3::PyResult; use revm::{Context, ContextWithHandlerCfg, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register}; use revm::inspectors::TracerEip3155; +use revm::precompile::Log; use revm::primitives::{ExecutionResult}; use revm::primitives::TransactTo; use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; @@ -40,6 +41,8 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra /// Calls the given evm. This is originally a copy of revm::Evm::transact, but it calls our own output function fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(ExecutionResult, EvmContext)> { + let logs_i = evm.context.evm.journaled_state.logs.len(); + evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; let initial_gas_spend = evm .handler @@ -97,8 +100,11 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(Executi post_exec.reimburse_caller(ctx, result.gas()).map_err(pyerr)?; // Reward beneficiary post_exec.reward_beneficiary(ctx, result.gas()).map_err(pyerr)?; + + let logs = ctx.evm.journaled_state.logs[logs_i..].to_vec(); + // Returns output of transaction. - Ok((output(ctx, result)?, evm.context.evm)) + Ok((output(ctx, result, logs)?, evm.context.evm)) } fn call_inputs(ctx: &&mut Context, gas_limit: u64, is_static: bool) -> Box { @@ -114,6 +120,7 @@ fn call_inputs(ctx: &&mut Context, gas_limit: u64, is_static: bool fn output( context: &mut Context, result: FrameResult, + logs: Vec, ) -> PyResult { replace(&mut context.evm.error, Ok(())).map_err(pyerr)?; // used gas with refund calculated. @@ -127,7 +134,7 @@ fn output( reason, gas_used: final_gas_used, gas_refunded, - logs: vec![], // todo: logs + logs, output, }, SuccessOrHalt::Revert => ExecutionResult::Revert { diff --git a/src/lib.rs b/src/lib.rs index 9daff0e..500ba68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,11 +25,13 @@ fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { // Types m.add_class::()?; - m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/src/types/execution_result.rs b/src/types/execution_result.rs index d47f76e..5eb6257 100644 --- a/src/types/execution_result.rs +++ b/src/types/execution_result.rs @@ -1,8 +1,34 @@ -use pyo3::{pyclass, pymethods}; -use revm::primitives::ExecutionResult as RevmExecutionResult; +use pyo3::{pyclass, pymethods, PyObject, Python}; +use pyo3::types::PyBytes; +use revm::primitives::{ExecutionResult as RevmExecutionResult, Log as RevmLog}; +#[derive(Debug, Clone, Hash)] +#[pyclass] +pub struct Log(RevmLog); -#[derive(Debug)] + +#[pymethods] +impl Log { + #[getter] + fn address(&self) -> String { + self.0.address.to_string() + } + + #[getter] + fn topics(&self) -> Vec { + self.0.topics().iter().map(|x| x.to_string()).collect() + } + + #[getter] + fn data(&self, py: Python<'_>) -> (Vec, PyObject) { + let topics = self.0.data.topics().iter().map(|t| PyBytes::new(py, &t.0).into()).collect(); + let data = PyBytes::new(py, &self.0.data.data).into(); + (topics, data) + } +} + +/// Result of a transaction execution. +#[derive(Debug, Clone, Hash)] #[pyclass(get_all)] pub struct ExecutionResult { is_success: bool, @@ -10,7 +36,7 @@ pub struct ExecutionResult { reason: String, gas_used: u64, gas_refunded: u64, - // TODO: logs: Vec, + logs: Vec, } #[pymethods] @@ -35,6 +61,23 @@ impl From for ExecutionResult { RevmExecutionResult::Success { gas_refunded, .. } => gas_refunded, _ => u64::default(), }, + logs: match result { + RevmExecutionResult::Success { logs, .. } => logs.into_iter().map(Log).collect(), + _ => Vec::new(), + }, } } } + +impl From for Log { + fn from(env: RevmLog) -> Self { + Log(env) + } +} + +impl From for RevmLog { + fn from(env: Log) -> Self { + env.0 + } +} + From a93fa47cc5e6b8a58c109c109f21320964eefb2e Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Mon, 25 Mar 2024 10:43:00 +0100 Subject: [PATCH 24/33] Review comments --- pyrevm.pyi | 3 +++ src/database.rs | 1 - src/types/checkpoint.rs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index ea54e5c..12aba2a 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -141,6 +141,9 @@ class EVM: """ Creates a new EVM instance. :param env: The environment. + :param fork_url: The fork URL. + :param fork_block_number: The fork block number. Either a block hash starting with 0x or a block number: + Supported block numbers: Latest, Finalized, Safe, Earliest, Pending :param gas_limit: The gas limit. :param tracing: Whether to enable tracing. :param spec_id: The spec ID. diff --git a/src/database.rs b/src/database.rs index d25d3c6..10c9d3a 100644 --- a/src/database.rs +++ b/src/database.rs @@ -38,7 +38,6 @@ impl DB { let provider = Provider::::try_from(fork_url).map_err(pyerr)?; let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; let db = EthersDB::new(Arc::new(provider), block).unwrap(); - // todo: do we need to get the blockEnv from the client? Ok(DB::Fork(CacheDB::new(db))) } diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs index 5939566..2fb5fce 100644 --- a/src/types/checkpoint.rs +++ b/src/types/checkpoint.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use pyo3::pyclass; #[pyclass(get_all)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct JournalCheckpoint{ pub log_i: usize, pub journal_i: usize, From 28fe7df481ccb094f3376a7d01127d92fd6f4e30 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Mon, 25 Mar 2024 11:31:57 +0100 Subject: [PATCH 25/33] Duplicate implementation --- src/types/checkpoint.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs index 2fb5fce..be6c9b9 100644 --- a/src/types/checkpoint.rs +++ b/src/types/checkpoint.rs @@ -1,4 +1,4 @@ -use std::hash::{Hash, Hasher}; +use std::hash::{Hash}; use pyo3::pyclass; @@ -8,10 +8,3 @@ pub struct JournalCheckpoint{ pub log_i: usize, pub journal_i: usize, } - -impl Hash for JournalCheckpoint { - fn hash(&self, state: &mut H) { - self.log_i.hash(state); - self.journal_i.hash(state); - } -} From 68db54669395b0a17fbec6da3906846d9dfbba93 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Tue, 26 Mar 2024 17:02:53 +0100 Subject: [PATCH 26/33] Support gas price --- pyrevm.pyi | 6 ++++-- pytest/test.py | 10 ++++++---- src/database.rs | 2 +- src/evm.rs | 29 +++++++++++++++++------------ src/executor.rs | 18 +++++++++++++++--- src/types/evm_env.rs | 8 ++++++++ 6 files changed, 51 insertions(+), 22 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index 12aba2a..8218997 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -182,6 +182,7 @@ class EVM: calldata: Optional[bytes] = None, value: Optional[int] = None, gas: Optional[int] = None, + gas_price: Optional[int] = None, is_static = False, ) -> bytes: """ @@ -189,8 +190,9 @@ class EVM: :param caller: The address of the caller. :param to: The address of the callee. :param calldata: The calldata. - :param value: The value. - :param gas: The gas. + :param value: The value to be transferred. + :param gas: The gas supplied for the call. + :param gas_price: The gas price for the call. Defaults to 0. :param is_static: Whether the call is static (i.e. does not change the state). :return: The return data and a list of changes to the state. """ diff --git a/pytest/test.py b/pytest/test.py index 7c1a16e..4c445c6 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -44,6 +44,8 @@ def test_revm_fork(): env=Env(block=BlockEnv(timestamp=100, prevrandao=bytes([0] * 32))), ) + assert evm.env.block.timestamp == 100 + vb_before = evm.basic(address) assert vb_before is not None @@ -95,11 +97,11 @@ def test_balances(): assert vb_before.balance == 0 # Give ether - AMT = 10000 - evm.set_balance(address, AMT) + amount = 10000 + evm.set_balance(address, amount) - assert evm.get_balance(address) == AMT - assert evm.basic(address).balance == AMT + assert evm.get_balance(address) == amount + assert evm.basic(address).balance == amount def test_balances_fork(): diff --git a/src/database.rs b/src/database.rs index 10c9d3a..aadccb6 100644 --- a/src/database.rs +++ b/src/database.rs @@ -37,7 +37,7 @@ impl DB { ) -> PyResult { let provider = Provider::::try_from(fork_url).map_err(pyerr)?; let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; - let db = EthersDB::new(Arc::new(provider), block).unwrap(); + let db = EthersDB::new(Arc::new(provider), block).unwrap_or_else(|| panic!("Could not create EthersDB")); Ok(DB::Fork(CacheDB::new(db))) } diff --git a/src/evm.rs b/src/evm.rs index 1f8287e..96a2f8c 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -8,7 +8,7 @@ use pyo3::types::PyBytes; use revm::{Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::precompile::{Address, Bytes}; use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; -use RevmExecutionResult::Success; +use revm::primitives::ExecutionResult::Success; use tracing::trace; use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; @@ -163,7 +163,7 @@ impl EVM { Ok(balance) } - #[pyo3(signature = (caller, to, calldata = None, value = None, gas = None, is_static = false))] + #[pyo3(signature = (caller, to, calldata = None, value = None, gas = None, gas_price = None, is_static = false))] pub fn message_call( &mut self, caller: &str, @@ -171,10 +171,11 @@ impl EVM { calldata: Option, value: Option, gas: Option, + gas_price: Option, is_static: bool, py: Python<'_>, ) -> PyResult { - let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into(), gas); + let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into(), gas, gas_price); match self.call_with_env(env, is_static) { Ok(data) => Ok(PyBytes::new(py, &data.to_vec()).into()), @@ -183,17 +184,18 @@ impl EVM { } /// Deploy a contract with the given code. - #[pyo3(signature = (deployer, code, value = None, gas = None, is_static = false, _abi = None))] + #[pyo3(signature = (deployer, code, value = None, gas = None, gas_price = None, is_static = false, _abi = None))] fn deploy( &mut self, deployer: &str, code: PyByteVec, value: Option, gas: Option, + gas_price: Option, is_static: bool, _abi: Option<&str>, ) -> PyResult { - let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.into(), value.unwrap_or_default(), gas); + let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.into(), value.unwrap_or_default(), gas, gas_price); match self.deploy_with_env(env, is_static) { Ok((_, address)) => Ok(format!("{:?}", address)), @@ -259,6 +261,7 @@ impl EVM { data: Bytes, value: U256, gas: Option, + gas_price: Option, ) -> RevmEnv { RevmEnv { cfg: self.context.env.cfg.clone(), @@ -276,7 +279,7 @@ impl EVM { data, value, // As above, we set the gas price to 0. - gas_price: U256::ZERO, + gas_price: gas_price.unwrap_or(U256::ZERO), gas_priority_fee: None, gas_limit: gas.unwrap_or(self.gas_limit).to(), ..self.context.env.tx.clone() @@ -296,9 +299,10 @@ impl EVM { let result = self.run_env(env, is_static)?; if let Success { output, .. } = result { - match output { - Output::Create(out, address) => Ok((out, address.unwrap())), - _ => Err(pyerr(output.clone())), + if let Output::Create(out, address) = output { + Ok((out, address.unwrap())) + } else { + Err(pyerr(output.clone())) } } else { Err(pyerr(result.clone())) @@ -314,9 +318,10 @@ impl EVM { let result = self.run_env(env, is_static)?; if let Success { output, .. } = result { - match output { - Output::Call(_) => Ok(output.clone().into_data()), - _ => Err(pyerr(output.clone())), + if let Output::Call(_) = output { + Ok(output.into_data()) + } else { + Err(pyerr(output.clone())) } } else { Err(pyerr(result.clone())) diff --git a/src/executor.rs b/src/executor.rs index 6392404..cd4e2ae 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,12 +1,15 @@ use std::mem::replace; + +use pyo3::exceptions::PyRuntimeError; use pyo3::PyResult; use revm::{Context, ContextWithHandlerCfg, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register}; use revm::inspectors::TracerEip3155; use revm::precompile::Log; -use revm::primitives::{ExecutionResult}; +use revm::primitives::{ExecutionResult, ShanghaiSpec}; use revm::primitives::TransactTo; -use revm_interpreter::{CallInputs, CreateInputs, SuccessOrHalt}; +use revm_interpreter::{CallInputs, CreateInputs, gas, SuccessOrHalt}; use revm_interpreter::primitives::HandlerCfg; + use crate::database::DB; use crate::utils::pyerr; @@ -48,7 +51,16 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(Executi .handler .validation() .initial_tx_gas(&evm.context.evm.env) - .map_err(pyerr)?; + .map_err(|e| { + let tx = &evm.context.evm.env.tx; + PyRuntimeError::new_err(format!( + "Initial gas spend is {} but gas limit is {}. Error: {:?}", + gas::validate_initial_tx_gas::(&tx.data, tx.transact_to.is_create(), &tx.access_list), + tx.gas_limit, + e + )) + })?; + evm.handler .validation() .tx_against_state(&mut evm.context) diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 42bc88a..a1030d9 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -31,6 +31,10 @@ impl Env { fn tx(&self) -> TxEnv { self.0.tx.clone().into() } + + fn __str__(&self) -> PyResult { + Ok(format!("{:?}", self)) + } } impl From for Env { @@ -139,6 +143,10 @@ impl TxEnv { } None } + + fn __str__(&self) -> PyResult { + Ok(format!("{:?}", self)) + } } impl From for RevmTxEnv { From 87cc4518cfc72c3300a1c0e3f53cb0e16891da06 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Wed, 27 Mar 2024 09:46:29 +0100 Subject: [PATCH 27/33] Fix and set block_env --- pyrevm.pyi | 6 ++++++ src/evm.rs | 13 ++++++++++--- src/types/evm_env.rs | 14 ++++++++++++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index 8218997..94d9153 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -14,6 +14,7 @@ class BlockEnv: prevrandao: Optional[bytes] = None, basefee: Optional[int] = None, gas_limit: Optional[int] = None, + excess_blob_gas: Optional[int] = None, ) -> "BlockEnv": ... @property @@ -30,6 +31,8 @@ class BlockEnv: def basefee(self) -> Optional[int]: ... @property def gas_limit(self) -> Optional[int]: ... + @property + def excess_blob_gas(self) -> Optional[int]: ... class TxEnv: def __new__( @@ -286,6 +289,9 @@ class EVM: def journal_state(self: "EVM") -> dict[str, AccountInfo]: """ The state in the journal. """ + def set_block_env(self: "EVM", block: BlockEnv) -> None: + """ Set the block environment. """ + class Log: @property diff --git a/src/evm.rs b/src/evm.rs index 96a2f8c..dd38171 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -7,11 +7,11 @@ use pyo3::exceptions::{PyKeyError, PyOverflowError}; use pyo3::types::PyBytes; use revm::{Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256}; use revm::precompile::{Address, Bytes}; -use revm::primitives::{BlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; +use revm::primitives::{CreateScheme, BlockEnv as RevmBlockEnv, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; use tracing::trace; -use crate::{types::{AccountInfo, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; +use crate::{types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; use crate::database::DB; use crate::executor::call_evm; use crate::types::{PyByteVec, PyDB}; @@ -247,6 +247,13 @@ impl EVM { ).collect() } + fn set_block_env(&mut self, block: BlockEnv) { + self.context.env.block = block.into(); + } + + fn __str__(&self) -> String { + format!("{:?}", self) + } } impl EVM { @@ -268,7 +275,7 @@ impl EVM { // We always set the gas price to 0, so we can execute the transaction regardless of // network conditions - the actual gas price is kept in `evm.block` and is applied by // the cheatcode handler if it is enabled - block: BlockEnv { + block: RevmBlockEnv { basefee: U256::ZERO, gas_limit: self.gas_limit, ..self.context.env.block.clone() diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index a1030d9..3389cd9 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -219,8 +219,8 @@ impl BlockEnv { } #[getter] - fn prevrandao(&self) -> Option<[u8; 32]> { - self.0.prevrandao.map(|i| i.0) + fn prevrandao(&self, py: Python<'_>) -> Option { + self.0.prevrandao.map(|i| PyBytes::new(py, &i.0.to_vec()).into()) } #[getter] @@ -228,6 +228,16 @@ impl BlockEnv { self.0.basefee } + #[getter] + fn gas_limit(&self) -> U256 { + self.0.gas_limit + } + + #[getter] + fn excess_blob_gas(&self) -> Option { + self.0.blob_excess_gas_and_price.clone().map(|i| i.excess_blob_gas) + } + fn __str__(&self) -> PyResult { Ok(format!("{:?}", self)) } From 72b6130ca4755226034614623d0206b48f873710 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 28 Mar 2024 04:02:15 +0100 Subject: [PATCH 28/33] chore: clippy --- src/database.rs | 2 +- src/empty_db_wrapper.rs | 6 ++--- src/evm.rs | 8 +++---- src/pystdout.rs | 2 +- src/types/evm_env.rs | 50 ++++++++++++++++++++++++----------------- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/database.rs b/src/database.rs index aadccb6..c6130ba 100644 --- a/src/database.rs +++ b/src/database.rs @@ -36,7 +36,7 @@ impl DB { fork_block_number: Option<&str>, ) -> PyResult { let provider = Provider::::try_from(fork_url).map_err(pyerr)?; - let block = fork_block_number.map(|n| BlockId::from_str(n)).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; + let block = fork_block_number.map(BlockId::from_str).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; let db = EthersDB::new(Arc::new(provider), block).unwrap_or_else(|| panic!("Could not create EthersDB")); Ok(DB::Fork(CacheDB::new(db))) } diff --git a/src/empty_db_wrapper.rs b/src/empty_db_wrapper.rs index da5fb04..c96d396 100644 --- a/src/empty_db_wrapper.rs +++ b/src/empty_db_wrapper.rs @@ -21,13 +21,13 @@ impl DatabaseRef for EmptyDBWrapper { } fn code_by_hash_ref(&self, code_hash: B256) -> Result { - Ok(self.0.code_by_hash_ref(code_hash)?) + self.0.code_by_hash_ref(code_hash) } fn storage_ref(&self, address: Address, index: U256) -> Result { - Ok(self.0.storage_ref(address, index)?) + self.0.storage_ref(address, index) } fn block_hash_ref(&self, number: U256) -> Result { - Ok(self.0.block_hash_ref(number)?) + self.0.block_hash_ref(number) } } diff --git a/src/evm.rs b/src/evm.rs index dd38171..e32bf01 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -110,7 +110,7 @@ impl EVM { if code.is_empty() { return Ok(None); } - Ok(Some(PyBytes::new(py, &code.bytecode.to_vec()).into())) + Ok(Some(PyBytes::new(py, code.bytecode.as_ref()).into())) } /// Get storage value of address at index. @@ -125,7 +125,7 @@ impl EVM { if bytes.is_empty() { return Ok(None); } - Ok(Some(PyBytes::new(py, &bytes.to_vec()).into())) + Ok(Some(PyBytes::new(py, bytes.as_ref()).into())) } /// Inserts the provided account information in the database at the specified address. @@ -175,10 +175,10 @@ impl EVM { is_static: bool, py: Python<'_>, ) -> PyResult { - let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default().into(), gas, gas_price); + let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default(), gas, gas_price); match self.call_with_env(env, is_static) { - Ok(data) => Ok(PyBytes::new(py, &data.to_vec()).into()), + Ok(data) => Ok(PyBytes::new(py, data.as_ref()).into()), Err(e) => Err(e), } } diff --git a/src/pystdout.rs b/src/pystdout.rs index d4b579f..506e5e1 100644 --- a/src/pystdout.rs +++ b/src/pystdout.rs @@ -12,7 +12,7 @@ impl Write for PySysStdout { Python::with_gil(|py| { let locals = PyDict::new(py); locals.set_item("s", s).unwrap(); - py.run("print(s, end='')", None, Some(&locals)).unwrap(); + py.run("print(s, end='')", None, Some(locals)).unwrap(); }); Ok(buf.len()) } diff --git a/src/types/evm_env.rs b/src/types/evm_env.rs index 3389cd9..5a5c923 100644 --- a/src/types/evm_env.rs +++ b/src/types/evm_env.rs @@ -1,6 +1,11 @@ use crate::utils::{addr, addr_or_zero}; -use pyo3::{exceptions::PyTypeError, pyclass, pymethods, PyObject, PyResult, Python, types::{PyBytes}}; -use revm::primitives::{BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256, CreateScheme}; +use pyo3::{ + exceptions::PyTypeError, pyclass, pymethods, types::PyBytes, PyObject, PyResult, Python, +}; +use revm::primitives::{ + BlobExcessGasAndPrice, BlockEnv as RevmBlockEnv, CfgEnv as RevmCfgEnv, CreateScheme, + Env as RevmEnv, TransactTo, TxEnv as RevmTxEnv, B256, U256, +}; #[pyclass] #[derive(Clone, Debug, Default)] @@ -75,7 +80,9 @@ impl TxEnv { gas_priority_fee: gas_priority_fee.map(Into::into), transact_to: match to { Some(inner) => TransactTo::call(addr(inner)?), - None => if salt.is_some() { TransactTo::create2(salt.unwrap()) } else { TransactTo::create() }, + None => salt + .map(TransactTo::create2) + .unwrap_or_else(TransactTo::create), }, value: value.unwrap_or_default(), data: data.unwrap_or_default().into(), @@ -121,7 +128,7 @@ impl TxEnv { #[getter] fn data(&self, py: Python<'_>) -> PyObject { - PyBytes::new(py, &self.0.data.to_vec()).into() + PyBytes::new(py, self.0.data.as_ref()).into() } #[getter] @@ -136,10 +143,8 @@ impl TxEnv { #[getter] fn salt(&self) -> Option { - if let TransactTo::Create(scheme) = self.0.transact_to { - if let CreateScheme::Create2 { salt } = scheme { - return Some(salt); - } + if let TransactTo::Create(CreateScheme::Create2 { salt }) = self.0.transact_to { + return Some(salt); } None } @@ -155,9 +160,9 @@ impl From for RevmTxEnv { } } -impl Into for RevmTxEnv { - fn into(self) -> TxEnv { - TxEnv(self) +impl From for TxEnv { + fn from(val: RevmTxEnv) -> Self { + TxEnv(val) } } @@ -199,7 +204,7 @@ impl BlockEnv { } #[getter] - fn number(&self) -> U256 { + fn number(&self) -> U256 { self.0.number } @@ -220,7 +225,9 @@ impl BlockEnv { #[getter] fn prevrandao(&self, py: Python<'_>) -> Option { - self.0.prevrandao.map(|i| PyBytes::new(py, &i.0.to_vec()).into()) + self.0 + .prevrandao + .map(|i| PyBytes::new(py, i.0.as_ref()).into()) } #[getter] @@ -235,7 +242,10 @@ impl BlockEnv { #[getter] fn excess_blob_gas(&self) -> Option { - self.0.blob_excess_gas_and_price.clone().map(|i| i.excess_blob_gas) + self.0 + .blob_excess_gas_and_price + .clone() + .map(|i| i.excess_blob_gas) } fn __str__(&self) -> PyResult { @@ -249,9 +259,9 @@ impl From for RevmBlockEnv { } } -impl Into for RevmBlockEnv { - fn into(self) -> BlockEnv { - BlockEnv(self) +impl From for BlockEnv { + fn from(val: RevmBlockEnv) -> Self { + BlockEnv(val) } } @@ -277,8 +287,8 @@ impl From for RevmCfgEnv { } } -impl Into for RevmCfgEnv { - fn into(self) -> CfgEnv { - CfgEnv(self) +impl From for CfgEnv { + fn from(val: RevmCfgEnv) -> Self { + CfgEnv(val) } } From f6e216313eb0d04c6c6f4317c0d45594df6a2244 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 28 Mar 2024 04:05:06 +0100 Subject: [PATCH 29/33] chore: run more stuff in CI, format code --- .github/workflows/rust.yml | 42 ++++++++++++++++- src/database.rs | 16 +++---- src/empty_db_wrapper.rs | 8 ++-- src/evm.rs | 89 +++++++++++++++++++++++------------ src/executor.rs | 65 +++++++++++++++++-------- src/lib.rs | 6 +-- src/pystdout.rs | 4 +- src/types/checkpoint.rs | 5 +- src/types/execution_result.rs | 12 +++-- src/types/mod.rs | 12 +++-- src/utils.rs | 2 +- 11 files changed, 179 insertions(+), 82 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5f604d6..4711095 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,9 +2,9 @@ name: rust on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ '*' ] + branches: ["*"] jobs: tests: @@ -27,3 +27,41 @@ jobs: - name: cargo test run: cargo test + + clippy: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - run: cargo clippy --workspace --all-targets --all-features + env: + RUSTFLAGS: -Dwarnings + + docs: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - run: cargo doc --workspace --all-features --no-deps --document-private-items + env: + RUSTDOCFLAGS: "--cfg docsrs -D warnings" + + fmt: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + - run: cargo fmt --all --check diff --git a/src/database.rs b/src/database.rs index c6130ba..d1c44db 100644 --- a/src/database.rs +++ b/src/database.rs @@ -4,10 +4,10 @@ use std::sync::Arc; use ethers_core::types::BlockId; use ethers_providers::{Http, Provider}; use pyo3::{PyErr, PyResult}; -use revm::Database; use revm::db::{CacheDB, DbAccount, EthersDB}; use revm::precompile::{Address, B256}; use revm::primitives::{AccountInfo, Bytecode, HashMap, State}; +use revm::Database; use revm_interpreter::primitives::db::{DatabaseCommit, DatabaseRef}; use ruint::aliases::U256; @@ -17,7 +17,6 @@ use crate::utils::pyerr; type MemDB = CacheDB; type ForkDB = CacheDB>>; - /// A wrapper around the `CacheDB` and `EthersDB` to provide a common interface /// without needing dynamic lifetime and generic parameters (unsupported in PyO3) #[derive(Clone, Debug)] @@ -31,13 +30,14 @@ impl DB { DB::Memory(MemDB::new(EmptyDBWrapper::default())) } - pub(crate) fn new_fork( - fork_url: &str, - fork_block_number: Option<&str>, - ) -> PyResult { + pub(crate) fn new_fork(fork_url: &str, fork_block_number: Option<&str>) -> PyResult { let provider = Provider::::try_from(fork_url).map_err(pyerr)?; - let block = fork_block_number.map(BlockId::from_str).map_or(Ok(None), |v| v.map(Some)).map_err(pyerr)?; - let db = EthersDB::new(Arc::new(provider), block).unwrap_or_else(|| panic!("Could not create EthersDB")); + let block = fork_block_number + .map(BlockId::from_str) + .map_or(Ok(None), |v| v.map(Some)) + .map_err(pyerr)?; + let db = EthersDB::new(Arc::new(provider), block) + .unwrap_or_else(|| panic!("Could not create EthersDB")); Ok(DB::Fork(CacheDB::new(db))) } diff --git a/src/empty_db_wrapper.rs b/src/empty_db_wrapper.rs index c96d396..7d7ff9a 100644 --- a/src/empty_db_wrapper.rs +++ b/src/empty_db_wrapper.rs @@ -1,14 +1,14 @@ -use std::convert::Infallible; +use revm::primitives::{Address, B256, U256}; use revm::{ db::{DatabaseRef, EmptyDB}, primitives::{AccountInfo, Bytecode}, }; -use revm::primitives::{Address, B256, U256}; +use std::convert::Infallible; /// An empty database that always returns default values when queried. /// This will also _always_ return `Some(AccountInfo)`. -/// Copied from Foundry: https://github.com/foundry-rs/foundry/blob/9e3ab9b3aff21c6e5ef/crates/evm/core/src/backend/in_memory_db.rs#L83-L92 - +/// +/// Copied from Foundry: #[derive(Clone, Debug, Default)] pub(crate) struct EmptyDBWrapper(EmptyDB); diff --git a/src/evm.rs b/src/evm.rs index e32bf01..c742f29 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -2,19 +2,25 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::mem::replace; -use pyo3::{pyclass, pymethods, PyObject, PyResult, Python}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; use pyo3::types::PyBytes; -use revm::{Evm, EvmContext, JournalCheckpoint as RevmCheckpoint, primitives::U256}; +use pyo3::{pyclass, pymethods, PyObject, PyResult, Python}; use revm::precompile::{Address, Bytes}; -use revm::primitives::{CreateScheme, BlockEnv as RevmBlockEnv, Env as RevmEnv, ExecutionResult as RevmExecutionResult, HandlerCfg, Output, SpecId, TransactTo, TxEnv}; use revm::primitives::ExecutionResult::Success; +use revm::primitives::{ + BlockEnv as RevmBlockEnv, CreateScheme, Env as RevmEnv, ExecutionResult as RevmExecutionResult, + HandlerCfg, Output, SpecId, TransactTo, TxEnv, +}; +use revm::{primitives::U256, Evm, EvmContext, JournalCheckpoint as RevmCheckpoint}; use tracing::trace; -use crate::{types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint}, utils::{addr, pyerr}}; use crate::database::DB; use crate::executor::call_evm; use crate::types::{PyByteVec, PyDB}; +use crate::{ + types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint}, + utils::{addr, pyerr}, +}; #[derive(Debug)] #[pyclass] @@ -57,12 +63,11 @@ impl EVM { ) -> PyResult { let spec = SpecId::from(spec_id); let env = env.unwrap_or_default().into(); - let db = fork_url.map(|url| DB::new_fork(url, fork_block_number)).unwrap_or(Ok(DB::new_memory()))?; + let db = fork_url + .map(|url| DB::new_fork(url, fork_block_number)) + .unwrap_or(Ok(DB::new_memory()))?; - let Evm { context, .. } = Evm::builder() - .with_env(Box::new(env)) - .with_db(db) - .build(); + let Evm { context, .. } = Evm::builder().with_env(Box::new(env)).with_db(db).build(); Ok(EVM { context: context.evm, gas_limit: U256::from(gas_limit), @@ -78,17 +83,23 @@ impl EVM { log_i: self.context.journaled_state.logs.len(), journal_i: self.context.journaled_state.journal.len(), }; - self.checkpoints.insert(checkpoint, self.context.journaled_state.checkpoint()); + self.checkpoints + .insert(checkpoint, self.context.journaled_state.checkpoint()); Ok(checkpoint) } fn revert(&mut self, checkpoint: JournalCheckpoint) -> PyResult<()> { if self.context.journaled_state.depth == 0 { - return Err(PyOverflowError::new_err(format!("No checkpoint to revert to: {:?}", self.context.journaled_state))); + return Err(PyOverflowError::new_err(format!( + "No checkpoint to revert to: {:?}", + self.context.journaled_state + ))); } if let Some(revm_checkpoint) = self.checkpoints.remove(&checkpoint) { - self.context.journaled_state.checkpoint_revert(revm_checkpoint); + self.context + .journaled_state + .checkpoint_revert(revm_checkpoint); Ok(()) } else { Err(PyKeyError::new_err("Invalid checkpoint")) @@ -129,11 +140,7 @@ impl EVM { } /// Inserts the provided account information in the database at the specified address. - fn insert_account_info( - &mut self, - address: &str, - info: AccountInfo, - ) -> PyResult<()> { + fn insert_account_info(&mut self, address: &str, info: AccountInfo) -> PyResult<()> { let target = addr(address)?; match self.context.journaled_state.state.get_mut(&target) { // account is cold, just insert into the DB, so it's retrieved next time @@ -175,9 +182,15 @@ impl EVM { is_static: bool, py: Python<'_>, ) -> PyResult { - let env = self.build_test_env(addr(caller)?, TransactTo::Call(addr(to)?), calldata.unwrap_or_default().into(), value.unwrap_or_default(), gas, gas_price); - match self.call_with_env(env, is_static) - { + let env = self.build_test_env( + addr(caller)?, + TransactTo::Call(addr(to)?), + calldata.unwrap_or_default().into(), + value.unwrap_or_default(), + gas, + gas_price, + ); + match self.call_with_env(env, is_static) { Ok(data) => Ok(PyBytes::new(py, data.as_ref()).into()), Err(e) => Err(e), } @@ -195,9 +208,15 @@ impl EVM { is_static: bool, _abi: Option<&str>, ) -> PyResult { - let env = self.build_test_env(addr(deployer)?, TransactTo::Create(CreateScheme::Create), code.into(), value.unwrap_or_default(), gas, gas_price); - match self.deploy_with_env(env, is_static) - { + let env = self.build_test_env( + addr(deployer)?, + TransactTo::Create(CreateScheme::Create), + code.into(), + value.unwrap_or_default(), + gas, + gas_price, + ); + match self.deploy_with_env(env, is_static) { Ok((_, address)) => Ok(format!("{:?}", address)), Err(e) => Err(e), } @@ -235,16 +254,22 @@ impl EVM { #[getter] fn db_accounts(&self) -> PyDB { - self.context.db.get_accounts().iter().map( - |(address, db_acc)| (address.to_string(), db_acc.info.clone().into()) - ).collect() + self.context + .db + .get_accounts() + .iter() + .map(|(address, db_acc)| (address.to_string(), db_acc.info.clone().into())) + .collect() } #[getter] fn journal_state(&self) -> PyDB { - self.context.journaled_state.state.iter().map( - |(address, acc)| (address.to_string(), acc.info.clone().into()) - ).collect() + self.context + .journaled_state + .state + .iter() + .map(|(address, acc)| (address.to_string(), acc.info.clone().into())) + .collect() } fn set_block_env(&mut self, block: BlockEnv) { @@ -337,8 +362,10 @@ impl EVM { fn run_env(&mut self, env: RevmEnv, is_static: bool) -> PyResult { self.context.env = Box::new(env); - let evm_context: EvmContext = replace(&mut self.context, EvmContext::new(DB::new_memory())); - let (result, evm_context) = call_evm(evm_context, self.handler_cfg, self.tracing, is_static)?; + let evm_context: EvmContext = + replace(&mut self.context, EvmContext::new(DB::new_memory())); + let (result, evm_context) = + call_evm(evm_context, self.handler_cfg, self.tracing, is_static)?; self.context = evm_context; self.result = Some(result.clone()); Ok(result) diff --git a/src/executor.rs b/src/executor.rs index cd4e2ae..062e552 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -2,19 +2,27 @@ use std::mem::replace; use pyo3::exceptions::PyRuntimeError; use pyo3::PyResult; -use revm::{Context, ContextWithHandlerCfg, Evm, EvmContext, FrameOrResult, FrameResult, inspector_handle_register}; use revm::inspectors::TracerEip3155; use revm::precompile::Log; -use revm::primitives::{ExecutionResult, ShanghaiSpec}; use revm::primitives::TransactTo; -use revm_interpreter::{CallInputs, CreateInputs, gas, SuccessOrHalt}; +use revm::primitives::{ExecutionResult, ShanghaiSpec}; +use revm::{ + inspector_handle_register, Context, ContextWithHandlerCfg, Evm, EvmContext, FrameOrResult, + FrameResult, +}; use revm_interpreter::primitives::HandlerCfg; +use revm_interpreter::{gas, CallInputs, CreateInputs, SuccessOrHalt}; use crate::database::DB; use crate::utils::pyerr; /// Calls the EVM with the given context and handler configuration. -pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tracing: bool, is_static: bool) -> PyResult<(ExecutionResult, EvmContext)> { +pub(crate) fn call_evm( + evm_context: EvmContext, + handler_cfg: HandlerCfg, + tracing: bool, + is_static: bool, +) -> PyResult<(ExecutionResult, EvmContext)> { if tracing { let tracer = TracerEip3155::new(Box::new(crate::pystdout::PySysStdout {}), true); let evm = Evm::builder() @@ -43,10 +51,16 @@ pub(crate) fn call_evm(evm_context: EvmContext, handler_cfg: HandlerCfg, tra } /// Calls the given evm. This is originally a copy of revm::Evm::transact, but it calls our own output function -fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(ExecutionResult, EvmContext)> { +fn run_evm( + mut evm: Evm<'_, EXT, DB>, + is_static: bool, +) -> PyResult<(ExecutionResult, EvmContext)> { let logs_i = evm.context.evm.journaled_state.logs.len(); - evm.handler.validation().env(&evm.context.evm.env).map_err(pyerr)?; + evm.handler + .validation() + .env(&evm.context.evm.env) + .map_err(pyerr)?; let initial_gas_spend = evm .handler .validation() @@ -55,7 +69,11 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(Executi let tx = &evm.context.evm.env.tx; PyRuntimeError::new_err(format!( "Initial gas spend is {} but gas limit is {}. Error: {:?}", - gas::validate_initial_tx_gas::(&tx.data, tx.transact_to.is_create(), &tx.access_list), + gas::validate_initial_tx_gas::( + &tx.data, + tx.transact_to.is_create(), + &tx.access_list + ), tx.gas_limit, e )) @@ -83,14 +101,15 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(Executi let exec = evm.handler.execution(); // call inner handling of call/create let first_frame_or_result = match ctx.evm.env.tx.transact_to { - TransactTo::Call(_) => exec.call( - ctx, - call_inputs(&ctx, gas_limit, is_static), - ).map_err(pyerr)?, - TransactTo::Create(_) => exec.create( - ctx, - CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), - ).map_err(pyerr)?, + TransactTo::Call(_) => exec + .call(ctx, call_inputs(&ctx, gas_limit, is_static)) + .map_err(pyerr)?, + TransactTo::Create(_) => exec + .create( + ctx, + CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + ) + .map_err(pyerr)?, }; // Starts the main running loop. @@ -109,9 +128,13 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(Executi let post_exec = evm.handler.post_execution(); // Reimburse the caller - post_exec.reimburse_caller(ctx, result.gas()).map_err(pyerr)?; + post_exec + .reimburse_caller(ctx, result.gas()) + .map_err(pyerr)?; // Reward beneficiary - post_exec.reward_beneficiary(ctx, result.gas()).map_err(pyerr)?; + post_exec + .reward_beneficiary(ctx, result.gas()) + .map_err(pyerr)?; let logs = ctx.evm.journaled_state.logs[logs_i..].to_vec(); @@ -119,7 +142,11 @@ fn run_evm(mut evm: Evm<'_, EXT, DB>, is_static: bool) -> PyResult<(Executi Ok((output(ctx, result, logs)?, evm.context.evm)) } -fn call_inputs(ctx: &&mut Context, gas_limit: u64, is_static: bool) -> Box { +fn call_inputs( + ctx: &&mut Context, + gas_limit: u64, + is_static: bool, +) -> Box { let mut inputs = CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(); inputs.is_static = is_static; inputs @@ -166,4 +193,4 @@ fn output( }; Ok(result) -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 500ba68..1365d27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,11 +13,11 @@ pub use types::*; mod evm; pub use evm::EVM; -mod utils; -mod empty_db_wrapper; mod database; -mod pystdout; +mod empty_db_wrapper; mod executor; +mod pystdout; +mod utils; #[pymodule] fn pyrevm(_py: Python<'_>, m: &PyModule) -> PyResult<()> { diff --git a/src/pystdout.rs b/src/pystdout.rs index 506e5e1..c1535fc 100644 --- a/src/pystdout.rs +++ b/src/pystdout.rs @@ -1,6 +1,6 @@ -use std::io::Write; -use pyo3::Python; use pyo3::types::PyDict; +use pyo3::Python; +use std::io::Write; pub(crate) struct PySysStdout; diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs index be6c9b9..d09b5a6 100644 --- a/src/types/checkpoint.rs +++ b/src/types/checkpoint.rs @@ -1,10 +1,9 @@ -use std::hash::{Hash}; - use pyo3::pyclass; +use std::hash::Hash; #[pyclass(get_all)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct JournalCheckpoint{ +pub struct JournalCheckpoint { pub log_i: usize, pub journal_i: usize, } diff --git a/src/types/execution_result.rs b/src/types/execution_result.rs index 5eb6257..33178f4 100644 --- a/src/types/execution_result.rs +++ b/src/types/execution_result.rs @@ -1,12 +1,11 @@ -use pyo3::{pyclass, pymethods, PyObject, Python}; use pyo3::types::PyBytes; +use pyo3::{pyclass, pymethods, PyObject, Python}; use revm::primitives::{ExecutionResult as RevmExecutionResult, Log as RevmLog}; #[derive(Debug, Clone, Hash)] #[pyclass] pub struct Log(RevmLog); - #[pymethods] impl Log { #[getter] @@ -21,7 +20,13 @@ impl Log { #[getter] fn data(&self, py: Python<'_>) -> (Vec, PyObject) { - let topics = self.0.data.topics().iter().map(|t| PyBytes::new(py, &t.0).into()).collect(); + let topics = self + .0 + .data + .topics() + .iter() + .map(|t| PyBytes::new(py, &t.0).into()) + .collect(); let data = PyBytes::new(py, &self.0.data.data).into(); (topics, data) } @@ -80,4 +85,3 @@ impl From for RevmLog { env.0 } } - diff --git a/src/types/mod.rs b/src/types/mod.rs index 84d94d8..de02f3e 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,14 +1,16 @@ use std::collections::HashMap; -pub use evm_env::*; -pub use info::*; -pub use execution_result::*; + +mod checkpoint; pub use checkpoint::*; mod evm_env; -mod info; +pub use evm_env::*; + mod execution_result; +pub use execution_result::*; -mod checkpoint; +mod info; +pub use info::*; // In Py03 we use vec to represent bytes pub(crate) type PyByteVec = Vec; diff --git a/src/utils.rs b/src/utils.rs index b14d974..dc414e6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use std::fmt::Debug; -use pyo3::{exceptions::PyTypeError, prelude::*}; use pyo3::exceptions::PyRuntimeError; +use pyo3::{exceptions::PyTypeError, prelude::*}; use revm::primitives::Address; pub(crate) fn addr(s: &str) -> Result { From b379feafbc4045888f8f421c1bd8d25c2db62286 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 28 Mar 2024 04:07:09 +0100 Subject: [PATCH 30/33] chore: less allocs --- src/evm.rs | 4 ++-- src/types/info.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/evm.rs b/src/evm.rs index c742f29..65bdd6c 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -353,10 +353,10 @@ impl EVM { if let Output::Call(_) = output { Ok(output.into_data()) } else { - Err(pyerr(output.clone())) + Err(pyerr(output)) } } else { - Err(pyerr(result.clone())) + Err(pyerr(result)) } } diff --git a/src/types/info.rs b/src/types/info.rs index f3c1127..3375899 100644 --- a/src/types/info.rs +++ b/src/types/info.rs @@ -22,8 +22,7 @@ impl AccountInfo { .0 .code .as_ref() - .map(|x| x.bytes().to_vec()) - .map(|bytes| PyBytes::new(py, &bytes).into()) + .map(|bytecode| PyBytes::new(py, bytecode.bytes()).into()) } #[getter] From a1e805253c2a2aa7303ba242bfec354f931a91c8 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 28 Mar 2024 04:08:09 +0100 Subject: [PATCH 31/33] chore: sort imports --- src/database.rs | 10 ++++------ src/evm.rs | 22 ++++++++++------------ src/executor.rs | 8 +++----- src/utils.rs | 3 +-- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/database.rs b/src/database.rs index d1c44db..8710e41 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,6 +1,5 @@ -use std::str::FromStr; -use std::sync::Arc; - +use crate::empty_db_wrapper::EmptyDBWrapper; +use crate::utils::pyerr; use ethers_core::types::BlockId; use ethers_providers::{Http, Provider}; use pyo3::{PyErr, PyResult}; @@ -10,9 +9,8 @@ use revm::primitives::{AccountInfo, Bytecode, HashMap, State}; use revm::Database; use revm_interpreter::primitives::db::{DatabaseCommit, DatabaseRef}; use ruint::aliases::U256; - -use crate::empty_db_wrapper::EmptyDBWrapper; -use crate::utils::pyerr; +use std::str::FromStr; +use std::sync::Arc; type MemDB = CacheDB; type ForkDB = CacheDB>>; diff --git a/src/evm.rs b/src/evm.rs index 65bdd6c..b3521c6 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -1,7 +1,10 @@ -use std::collections::{HashMap, HashSet}; -use std::fmt::Debug; -use std::mem::replace; - +use crate::database::DB; +use crate::executor::call_evm; +use crate::types::{PyByteVec, PyDB}; +use crate::{ + types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint}, + utils::{addr, pyerr}, +}; use pyo3::exceptions::{PyKeyError, PyOverflowError}; use pyo3::types::PyBytes; use pyo3::{pyclass, pymethods, PyObject, PyResult, Python}; @@ -12,16 +15,11 @@ use revm::primitives::{ HandlerCfg, Output, SpecId, TransactTo, TxEnv, }; use revm::{primitives::U256, Evm, EvmContext, JournalCheckpoint as RevmCheckpoint}; +use std::collections::{HashMap, HashSet}; +use std::fmt::Debug; +use std::mem::replace; use tracing::trace; -use crate::database::DB; -use crate::executor::call_evm; -use crate::types::{PyByteVec, PyDB}; -use crate::{ - types::{AccountInfo, BlockEnv, Env, ExecutionResult, JournalCheckpoint}, - utils::{addr, pyerr}, -}; - #[derive(Debug)] #[pyclass] pub struct EVM { diff --git a/src/executor.rs b/src/executor.rs index 062e552..6d38409 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,5 +1,5 @@ -use std::mem::replace; - +use crate::database::DB; +use crate::utils::pyerr; use pyo3::exceptions::PyRuntimeError; use pyo3::PyResult; use revm::inspectors::TracerEip3155; @@ -12,9 +12,7 @@ use revm::{ }; use revm_interpreter::primitives::HandlerCfg; use revm_interpreter::{gas, CallInputs, CreateInputs, SuccessOrHalt}; - -use crate::database::DB; -use crate::utils::pyerr; +use std::mem::replace; /// Calls the EVM with the given context and handler configuration. pub(crate) fn call_evm( diff --git a/src/utils.rs b/src/utils.rs index dc414e6..bee54be 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,7 @@ -use std::fmt::Debug; - use pyo3::exceptions::PyRuntimeError; use pyo3::{exceptions::PyTypeError, prelude::*}; use revm::primitives::Address; +use std::fmt::Debug; pub(crate) fn addr(s: &str) -> Result { s.parse::
() From 50b7faeb5c1c87ec7efa0c8ba5f2c4dbc9a24982 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Thu, 4 Apr 2024 11:30:22 +0200 Subject: [PATCH 32/33] Rename to fork_block --- pyrevm.pyi | 4 ++-- pytest/test.py | 4 ++-- src/database.rs | 4 ++-- src/evm.rs | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyrevm.pyi b/pyrevm.pyi index 94d9153..d1a5915 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -136,7 +136,7 @@ class EVM: cls: Type["EVM"], env: Optional[Env] = None, fork_url: Optional[str] = None, - fork_block_number: Optional[str] = None, + fork_block: Optional[str] = None, gas_limit: int = 2**64 - 1, tracing: bool = False, spec_id="SHANGHAI", @@ -145,7 +145,7 @@ class EVM: Creates a new EVM instance. :param env: The environment. :param fork_url: The fork URL. - :param fork_block_number: The fork block number. Either a block hash starting with 0x or a block number: + :param fork_block: The fork block number. Either a block hash starting with 0x or a block number: Supported block numbers: Latest, Finalized, Safe, Earliest, Pending :param gas_limit: The gas limit. :param tracing: Whether to enable tracing. diff --git a/pytest/test.py b/pytest/test.py index 4c445c6..90e23ed 100644 --- a/pytest/test.py +++ b/pytest/test.py @@ -11,7 +11,7 @@ KWARG_CASES = [ {"fork_url": fork_url}, - {"fork_url": fork_url, "tracing": False, "fork_block_number": "latest"}, + {"fork_url": fork_url, "tracing": False, "fork_block": "latest"}, {}, ] @@ -105,7 +105,7 @@ def test_balances(): def test_balances_fork(): - evm = EVM(fork_url=fork_url, fork_block_number="0x3b01f793ed1923cd82df5fe345b3e12211aedd514c8546e69efd6386dc0c9a97") + evm = EVM(fork_url=fork_url, fork_block="0x3b01f793ed1923cd82df5fe345b3e12211aedd514c8546e69efd6386dc0c9a97") vb_before = evm.basic(address) assert vb_before.balance == 955628344913799071315 diff --git a/src/database.rs b/src/database.rs index 8710e41..3022354 100644 --- a/src/database.rs +++ b/src/database.rs @@ -28,9 +28,9 @@ impl DB { DB::Memory(MemDB::new(EmptyDBWrapper::default())) } - pub(crate) fn new_fork(fork_url: &str, fork_block_number: Option<&str>) -> PyResult { + pub(crate) fn new_fork(fork_url: &str, fork_block: Option<&str>) -> PyResult { let provider = Provider::::try_from(fork_url).map_err(pyerr)?; - let block = fork_block_number + let block = fork_block .map(BlockId::from_str) .map_or(Ok(None), |v| v.map(Some)) .map_err(pyerr)?; diff --git a/src/evm.rs b/src/evm.rs index b3521c6..79db834 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -50,11 +50,11 @@ pub struct EVM { impl EVM { /// Create a new EVM instance. #[new] - #[pyo3(signature = (env = None, fork_url = None, fork_block_number = None, gas_limit = 18446744073709551615, tracing = false, spec_id = "LATEST"))] + #[pyo3(signature = (env = None, fork_url = None, fork_block = None, gas_limit = 18446744073709551615, tracing = false, spec_id = "LATEST"))] fn new( env: Option, fork_url: Option<&str>, - fork_block_number: Option<&str>, + fork_block: Option<&str>, gas_limit: u64, tracing: bool, spec_id: &str, @@ -62,7 +62,7 @@ impl EVM { let spec = SpecId::from(spec_id); let env = env.unwrap_or_default().into(); let db = fork_url - .map(|url| DB::new_fork(url, fork_block_number)) + .map(|url| DB::new_fork(url, fork_block)) .unwrap_or(Ok(DB::new_memory()))?; let Evm { context, .. } = Evm::builder().with_env(Box::new(env)).with_db(db).build(); From 525ec28d95adb17378ae2041649894f28daf08f7 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Thu, 4 Apr 2024 20:46:44 +0200 Subject: [PATCH 33/33] Add reset_transient_storage --- pyrevm.pyi | 3 +++ src/evm.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/pyrevm.pyi b/pyrevm.pyi index d1a5915..de7f9f1 100644 --- a/pyrevm.pyi +++ b/pyrevm.pyi @@ -292,6 +292,9 @@ class EVM: def set_block_env(self: "EVM", block: BlockEnv) -> None: """ Set the block environment. """ + def reset_transient_storage(self: "EVM") -> None: + """ Reset the transient storage. """ + class Log: @property diff --git a/src/evm.rs b/src/evm.rs index 79db834..b03fb0a 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -274,6 +274,10 @@ impl EVM { self.context.env.block = block.into(); } + fn reset_transient_storage(&mut self) { + self.context.journaled_state.transient_storage.clear(); + } + fn __str__(&self) -> String { format!("{:?}", self) }