From 8de3ed6b4352195b4baf948e2a8ebeb2832f089b Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Thu, 22 Aug 2024 18:15:02 +0100 Subject: [PATCH 1/5] feat(rpc): add preimages to execution witness response --- crates/rpc/rpc/src/debug.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 32ff728ef2b..1e5b3121e57 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -8,7 +8,7 @@ use reth_primitives::{ }; use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, HeaderProvider, StateProofProvider, - StateProviderFactory, TransactionVariant, + StateProviderFactory, StateRootProvider, TransactionVariant, }; use reth_revm::{database::StateProviderDatabase, state_change::apply_blockhashes_update}; use reth_rpc_api::DebugApiServer; @@ -27,7 +27,7 @@ use reth_rpc_types::{ BlockError, Bundle, RichBlock, StateContext, TransactionRequest, }; use reth_tasks::pool::BlockingTaskGuard; -use reth_trie::{HashedPostState, HashedStorage}; +use reth_trie::{HashedPostState, HashedStorage, TrieAccount}; use revm::{ db::{states::bundle_state::BundleRetention, CacheDB}, primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg}, @@ -628,6 +628,10 @@ where // Take the bundle state let bundle_state = db.take_bundle(); + // Initialize a map of preimages. The length will be >= the number of accounts in + // the cache. + let mut state_preimages = HashMap::with_capacity(db.cache.accounts.len()); + // Grab all account proofs for the data accessed during block execution. // // Note: We grab *all* accounts in the cache here, as the `BundleState` prunes @@ -646,9 +650,24 @@ where .or_insert_with(|| HashedStorage::new(account.status.was_destroyed())); if let Some(account) = account.account { + let storage_root = db + .database + .hashed_storage_root(address, storage.clone()) + .map_err(Eth::Error::from_eth_err); + + state_preimages.insert( + hashed_address, + alloy_rlp::encode(TrieAccount::from(( + account.info.clone(), + storage_root?, + ))), + ); + for (slot, value) in account.storage { let hashed_slot = keccak256(B256::from(slot)); storage.storage.insert(hashed_slot, value); + + state_preimages.insert(hashed_slot, alloy_rlp::encode(value)); } } } @@ -659,6 +678,9 @@ where let witness = state_provider .witness(HashedPostState::default(), hashed_state) .map_err(Into::into)?; + + // TODO(alexey): return `state_preimages` as well when https://github.com/alloy-rs/alloy/pull/1178 is merged + Ok(witness) }) .await From 2b4d9d9a6ed1c349a7db0a52e838f87bf45afa2c Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Thu, 22 Aug 2024 18:42:57 +0100 Subject: [PATCH 2/5] store unhashed keys as preimages --- crates/rpc/rpc/src/debug.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 1e5b3121e57..881b2eff0cf 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -8,7 +8,7 @@ use reth_primitives::{ }; use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, HeaderProvider, StateProofProvider, - StateProviderFactory, StateRootProvider, TransactionVariant, + StateProviderFactory, TransactionVariant, }; use reth_revm::{database::StateProviderDatabase, state_change::apply_blockhashes_update}; use reth_rpc_api::DebugApiServer; @@ -27,7 +27,7 @@ use reth_rpc_types::{ BlockError, Bundle, RichBlock, StateContext, TransactionRequest, }; use reth_tasks::pool::BlockingTaskGuard; -use reth_trie::{HashedPostState, HashedStorage, TrieAccount}; +use reth_trie::{HashedPostState, HashedStorage}; use revm::{ db::{states::bundle_state::BundleRetention, CacheDB}, primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg}, @@ -650,24 +650,14 @@ where .or_insert_with(|| HashedStorage::new(account.status.was_destroyed())); if let Some(account) = account.account { - let storage_root = db - .database - .hashed_storage_root(address, storage.clone()) - .map_err(Eth::Error::from_eth_err); - - state_preimages.insert( - hashed_address, - alloy_rlp::encode(TrieAccount::from(( - account.info.clone(), - storage_root?, - ))), - ); + state_preimages.insert(hashed_address, alloy_rlp::encode(address)); for (slot, value) in account.storage { - let hashed_slot = keccak256(B256::from(slot)); + let slot = B256::from(slot); + let hashed_slot = keccak256(slot); storage.storage.insert(hashed_slot, value); - state_preimages.insert(hashed_slot, alloy_rlp::encode(value)); + state_preimages.insert(hashed_slot, alloy_rlp::encode(slot)); } } } From 8df597a648d5753fe6f9c3c75ee9180b172a046f Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Fri, 23 Aug 2024 10:38:56 +0100 Subject: [PATCH 3/5] do not init with capacity --- crates/rpc/rpc/src/debug.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 881b2eff0cf..2499cfc8d68 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -628,9 +628,8 @@ where // Take the bundle state let bundle_state = db.take_bundle(); - // Initialize a map of preimages. The length will be >= the number of accounts in - // the cache. - let mut state_preimages = HashMap::with_capacity(db.cache.accounts.len()); + // Initialize a map of preimages. + let mut state_preimages = HashMap::new(); // Grab all account proofs for the data accessed during block execution. // @@ -669,7 +668,7 @@ where .witness(HashedPostState::default(), hashed_state) .map_err(Into::into)?; - // TODO(alexey): return `state_preimages` as well when https://github.com/alloy-rs/alloy/pull/1178 is merged + // TODO(alexey): return `state_preimages` as well when https://github.com/alloy-rs/alloy/pull/1178 is released Ok(witness) }) From 797752cf9b8b81b823833c0fa43707b87880fdc3 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Thu, 29 Aug 2024 16:49:32 +0100 Subject: [PATCH 4/5] return a new struct, accept another argument for preimages --- Cargo.lock | 23 ++++++++++++++------- crates/rpc/rpc-api/src/debug.rs | 8 +++++--- crates/rpc/rpc-types/Cargo.toml | 22 ++++++++++---------- crates/rpc/rpc-types/src/eth/mod.rs | 4 ---- crates/rpc/rpc-types/src/lib.rs | 32 ++++------------------------- crates/rpc/rpc/src/debug.rs | 25 ++++++++++++++-------- 6 files changed, 53 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16177acf612..f4a73f98704 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,9 +436,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d758f65aa648491c6358335c578de45cd7de6fdf2877c3cef61f2c9bebea21" dependencies = [ + "alloy-rpc-types-admin", + "alloy-rpc-types-anvil", + "alloy-rpc-types-beacon", + "alloy-rpc-types-debug", "alloy-rpc-types-engine", "alloy-rpc-types-eth", + "alloy-rpc-types-mev", "alloy-rpc-types-trace", + "alloy-rpc-types-txpool", "alloy-serde", "serde", ] @@ -480,6 +486,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-rpc-types-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99137a6d8d559138ed5a64f0e270ef095abc84d36b52727621d3ba845ed5d5d1" +dependencies = [ + "alloy-primitives 0.8.0", + "serde", +] + [[package]] name = "alloy-rpc-types-engine" version = "0.3.0" @@ -8400,13 +8416,6 @@ version = "1.0.5" dependencies = [ "alloy-primitives 0.8.0", "alloy-rpc-types", - "alloy-rpc-types-admin", - "alloy-rpc-types-anvil", - "alloy-rpc-types-beacon", - "alloy-rpc-types-engine", - "alloy-rpc-types-mev", - "alloy-rpc-types-trace", - "alloy-rpc-types-txpool", "alloy-serde", "arbitrary", "jsonrpsee-types", diff --git a/crates/rpc/rpc-api/src/debug.rs b/crates/rpc/rpc-api/src/debug.rs index ab755b25831..3fba43da63d 100644 --- a/crates/rpc/rpc-api/src/debug.rs +++ b/crates/rpc/rpc-api/src/debug.rs @@ -1,13 +1,13 @@ use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, B256}; use reth_rpc_types::{ + debug::ExecutionWitness, trace::geth::{ BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult, }, Block, Bundle, StateContext, TransactionRequest, }; -use std::collections::HashMap; /// Debug rpc interface. #[cfg_attr(not(feature = "client"), rpc(server, namespace = "debug"))] @@ -138,12 +138,14 @@ pub trait DebugApi { /// to their preimages that were required during the execution of the block, including during /// state root recomputation. /// - /// The first and only argument is the block number or block hash. + /// The first argument is the block number or block hash. The second argument is a boolean + /// indicating whether to include the preimages of keys in the response. #[method(name = "executionWitness")] async fn debug_execution_witness( &self, block: BlockNumberOrTag, - ) -> RpcResult>; + include_preimages: bool, + ) -> RpcResult; /// Sets the logging backtrace location. When a backtrace location is set and a log message is /// emitted at that location, the stack of the goroutine executing the log statement will diff --git a/crates/rpc/rpc-types/Cargo.toml b/crates/rpc/rpc-types/Cargo.toml index 988716f6da4..003edd1f5b6 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -15,15 +15,16 @@ workspace = true # ethereum alloy-primitives = { workspace = true, features = ["rand", "rlp", "serde"] } -alloy-rpc-types.workspace = true -alloy-rpc-types-admin.workspace = true -alloy-rpc-types-anvil.workspace = true -alloy-rpc-types-beacon = { workspace = true, optional = true } -alloy-rpc-types-mev.workspace = true -alloy-rpc-types-trace.workspace = true -alloy-rpc-types-txpool.workspace = true +alloy-rpc-types = { workspace = true, features = [ + "admin", + "anvil", + "debug", + "engine", + "mev", + "trace", + "txpool" +] } alloy-serde.workspace = true -alloy-rpc-types-engine = { workspace = true, features = ["jsonrpsee-types"], optional = true } # optimism op-alloy-rpc-types.workspace = true @@ -42,9 +43,8 @@ rand.workspace = true default = ["jsonrpsee-types"] jsonrpsee-types = [ "dep:jsonrpsee-types", - "dep:alloy-rpc-types-beacon", - "dep:alloy-rpc-types-engine", "alloy-rpc-types/jsonrpsee-types", - "alloy-rpc-types-engine/jsonrpsee-types", + "alloy-rpc-types/beacon", + "alloy-rpc-types/engine", ] arbitrary = ["alloy-primitives/arbitrary", "alloy-rpc-types/arbitrary"] diff --git a/crates/rpc/rpc-types/src/eth/mod.rs b/crates/rpc/rpc-types/src/eth/mod.rs index 3f6c67ac5c2..92e6940ff8a 100644 --- a/crates/rpc/rpc-types/src/eth/mod.rs +++ b/crates/rpc/rpc-types/src/eth/mod.rs @@ -2,7 +2,3 @@ pub(crate) mod error; pub mod transaction; - -// re-export -#[cfg(feature = "jsonrpsee-types")] -pub use alloy_rpc_types_engine as engine; diff --git a/crates/rpc/rpc-types/src/lib.rs b/crates/rpc/rpc-types/src/lib.rs index e886d549ad3..75dda9793a8 100644 --- a/crates/rpc/rpc-types/src/lib.rs +++ b/crates/rpc/rpc-types/src/lib.rs @@ -25,38 +25,14 @@ pub use alloy_rpc_types::*; // Ethereum specific serde types coming from alloy. pub use alloy_serde::*; -pub mod trace { - //! RPC types for trace endpoints and inspectors. - pub use alloy_rpc_types_trace::*; -} - -// re-export admin -pub use alloy_rpc_types_admin as admin; - -// Anvil specific rpc types coming from alloy. -pub use alloy_rpc_types_anvil as anvil; - -// re-export mev -pub use alloy_rpc_types_mev as mev; - -// re-export beacon -#[cfg(feature = "jsonrpsee-types")] -pub use alloy_rpc_types_beacon as beacon; - -// re-export txpool -pub use alloy_rpc_types_txpool as txpool; - // Ethereum specific rpc types related to typed transaction requests and the engine API. #[cfg(feature = "jsonrpsee-types")] +pub use alloy_rpc_types::engine::{ + ExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, PayloadError, +}; +#[cfg(feature = "jsonrpsee-types")] pub use eth::error::ToRpcError; pub use eth::transaction::{self, TransactionRequest, TypedTransactionRequest}; -#[cfg(feature = "jsonrpsee-types")] -pub use eth::{ - engine, - engine::{ - ExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, PayloadError, - }, -}; /// Optimism specific rpc types. pub mod optimism { diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 7c87cc311d6..20e70ae0bbe 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -22,6 +22,7 @@ use reth_rpc_eth_api::{ use reth_rpc_eth_types::{EthApiError, StateCacheDb}; use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; use reth_rpc_types::{ + debug::ExecutionWitness, state::EvmOverrides, trace::geth::{ BlockTraceResult, FourByteFrame, GethDebugBuiltInTracerType, GethDebugTracerType, @@ -567,7 +568,8 @@ where pub async fn debug_execution_witness( &self, block_id: BlockNumberOrTag, - ) -> Result, Eth::Error> { + include_preimages: bool, + ) -> Result { let ((cfg, block_env, _), maybe_block) = futures::try_join!( self.inner.eth_api.evm_env_at(block_id.into()), self.inner.eth_api.block_with_senders(block_id.into()), @@ -649,14 +651,19 @@ where .or_insert_with(|| HashedStorage::new(account.status.was_destroyed())); if let Some(account) = account.account { - state_preimages.insert(hashed_address, alloy_rlp::encode(address)); + if include_preimages { + state_preimages + .insert(hashed_address, alloy_rlp::encode(address).into()); + } for (slot, value) in account.storage { let slot = B256::from(slot); let hashed_slot = keccak256(slot); storage.storage.insert(hashed_slot, value); - state_preimages.insert(hashed_slot, alloy_rlp::encode(slot)); + if include_preimages { + state_preimages.insert(hashed_slot, alloy_rlp::encode(slot).into()); + } } } } @@ -668,9 +675,10 @@ where .witness(HashedPostState::default(), hashed_state) .map_err(Into::into)?; - // TODO(alexey): return `state_preimages` as well when https://github.com/alloy-rs/alloy/pull/1178 is released - - Ok(witness) + Ok(ExecutionWitness { + witness, + state_preimages: include_preimages.then_some(state_preimages), + }) }) .await } @@ -942,9 +950,10 @@ where async fn debug_execution_witness( &self, block: BlockNumberOrTag, - ) -> RpcResult> { + include_preimages: bool, + ) -> RpcResult { let _permit = self.acquire_trace_permit().await; - Self::debug_execution_witness(self, block).await.map_err(Into::into) + Self::debug_execution_witness(self, block, include_preimages).await.map_err(Into::into) } /// Handler for `debug_traceCall` From e83968c79dc21e900e473256fee6b1326f5269da Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Thu, 29 Aug 2024 16:52:40 +0100 Subject: [PATCH 5/5] revert alloy rpc types deps collapse --- Cargo.lock | 14 +++++++----- Cargo.toml | 1 + crates/rpc/rpc-types/Cargo.toml | 23 ++++++++++--------- crates/rpc/rpc-types/src/eth/mod.rs | 4 ++++ crates/rpc/rpc-types/src/lib.rs | 35 +++++++++++++++++++++++++---- 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4a73f98704..42824583039 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,15 +436,9 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d758f65aa648491c6358335c578de45cd7de6fdf2877c3cef61f2c9bebea21" dependencies = [ - "alloy-rpc-types-admin", - "alloy-rpc-types-anvil", - "alloy-rpc-types-beacon", - "alloy-rpc-types-debug", "alloy-rpc-types-engine", "alloy-rpc-types-eth", - "alloy-rpc-types-mev", "alloy-rpc-types-trace", - "alloy-rpc-types-txpool", "alloy-serde", "serde", ] @@ -8416,6 +8410,14 @@ version = "1.0.5" dependencies = [ "alloy-primitives 0.8.0", "alloy-rpc-types", + "alloy-rpc-types-admin", + "alloy-rpc-types-anvil", + "alloy-rpc-types-beacon", + "alloy-rpc-types-debug", + "alloy-rpc-types-engine", + "alloy-rpc-types-mev", + "alloy-rpc-types-trace", + "alloy-rpc-types-txpool", "alloy-serde", "arbitrary", "jsonrpsee-types", diff --git a/Cargo.toml b/Cargo.toml index 9cfaaeb4609..097f18aec07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -430,6 +430,7 @@ alloy-rpc-types = { version = "0.3.0", features = [ alloy-rpc-types-admin = { version = "0.3.0", default-features = false } alloy-rpc-types-anvil = { version = "0.3.0", default-features = false } alloy-rpc-types-beacon = { version = "0.3.0", default-features = false } +alloy-rpc-types-debug = { version = "0.3.0", default-features = false } alloy-rpc-types-engine = { version = "0.3.0", default-features = false } alloy-rpc-types-eth = { version = "0.3.0", default-features = false } alloy-rpc-types-mev = { version = "0.3.0", default-features = false } diff --git a/crates/rpc/rpc-types/Cargo.toml b/crates/rpc/rpc-types/Cargo.toml index 003edd1f5b6..32362cc3007 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -15,16 +15,16 @@ workspace = true # ethereum alloy-primitives = { workspace = true, features = ["rand", "rlp", "serde"] } -alloy-rpc-types = { workspace = true, features = [ - "admin", - "anvil", - "debug", - "engine", - "mev", - "trace", - "txpool" -] } +alloy-rpc-types.workspace = true +alloy-rpc-types-admin.workspace = true +alloy-rpc-types-anvil.workspace = true +alloy-rpc-types-beacon = { workspace = true, optional = true } +alloy-rpc-types-mev.workspace = true +alloy-rpc-types-trace.workspace = true +alloy-rpc-types-txpool.workspace = true +alloy-rpc-types-debug.workspace = true alloy-serde.workspace = true +alloy-rpc-types-engine = { workspace = true, features = ["jsonrpsee-types"], optional = true } # optimism op-alloy-rpc-types.workspace = true @@ -43,8 +43,9 @@ rand.workspace = true default = ["jsonrpsee-types"] jsonrpsee-types = [ "dep:jsonrpsee-types", + "dep:alloy-rpc-types-beacon", + "dep:alloy-rpc-types-engine", "alloy-rpc-types/jsonrpsee-types", - "alloy-rpc-types/beacon", - "alloy-rpc-types/engine", + "alloy-rpc-types-engine/jsonrpsee-types", ] arbitrary = ["alloy-primitives/arbitrary", "alloy-rpc-types/arbitrary"] diff --git a/crates/rpc/rpc-types/src/eth/mod.rs b/crates/rpc/rpc-types/src/eth/mod.rs index 92e6940ff8a..3f6c67ac5c2 100644 --- a/crates/rpc/rpc-types/src/eth/mod.rs +++ b/crates/rpc/rpc-types/src/eth/mod.rs @@ -2,3 +2,7 @@ pub(crate) mod error; pub mod transaction; + +// re-export +#[cfg(feature = "jsonrpsee-types")] +pub use alloy_rpc_types_engine as engine; diff --git a/crates/rpc/rpc-types/src/lib.rs b/crates/rpc/rpc-types/src/lib.rs index 75dda9793a8..dc0eb3dec5c 100644 --- a/crates/rpc/rpc-types/src/lib.rs +++ b/crates/rpc/rpc-types/src/lib.rs @@ -25,14 +25,41 @@ pub use alloy_rpc_types::*; // Ethereum specific serde types coming from alloy. pub use alloy_serde::*; -// Ethereum specific rpc types related to typed transaction requests and the engine API. +pub mod trace { + //! RPC types for trace endpoints and inspectors. + pub use alloy_rpc_types_trace::*; +} + +// re-export admin +pub use alloy_rpc_types_admin as admin; + +// Anvil specific rpc types coming from alloy. +pub use alloy_rpc_types_anvil as anvil; + +// re-export mev +pub use alloy_rpc_types_mev as mev; + +// re-export beacon #[cfg(feature = "jsonrpsee-types")] -pub use alloy_rpc_types::engine::{ - ExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, PayloadError, -}; +pub use alloy_rpc_types_beacon as beacon; + +// re-export txpool +pub use alloy_rpc_types_txpool as txpool; + +// re-export debug +pub use alloy_rpc_types_debug as debug; + +// Ethereum specific rpc types related to typed transaction requests and the engine API. #[cfg(feature = "jsonrpsee-types")] pub use eth::error::ToRpcError; pub use eth::transaction::{self, TransactionRequest, TypedTransactionRequest}; +#[cfg(feature = "jsonrpsee-types")] +pub use eth::{ + engine, + engine::{ + ExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, PayloadError, + }, +}; /// Optimism specific rpc types. pub mod optimism {