From ef975f15eb8d1a04e13915d628ab705257f6d45d Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Mon, 2 Sep 2024 10:25:38 +0100 Subject: [PATCH] feat(rpc): add preimages to execution witness response (#10456) Co-authored-by: Roman Krasiuk --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + crates/rpc/rpc-api/src/debug.rs | 8 +++++--- crates/rpc/rpc-types/Cargo.toml | 1 + crates/rpc/rpc-types/src/lib.rs | 3 +++ crates/rpc/rpc/src/debug.rs | 30 +++++++++++++++++++++++++----- 6 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dbc4a4632de..c7e48f85c6f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -480,6 +480,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" @@ -8371,6 +8381,7 @@ dependencies = [ "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", diff --git a/Cargo.toml b/Cargo.toml index c7786f8676ca..cda62c481f7c 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-api/src/debug.rs b/crates/rpc/rpc-api/src/debug.rs index ab755b258314..3fba43da63dd 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 988716f6da43..32362cc3007c 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -22,6 +22,7 @@ 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 } diff --git a/crates/rpc/rpc-types/src/lib.rs b/crates/rpc/rpc-types/src/lib.rs index e886d549ad3c..dc0eb3dec5c9 100644 --- a/crates/rpc/rpc-types/src/lib.rs +++ b/crates/rpc/rpc-types/src/lib.rs @@ -46,6 +46,9 @@ 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; diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 44cbdef1b7d9..20e70ae0bbe0 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()), @@ -628,6 +630,9 @@ where // Take the bundle state let bundle_state = db.take_bundle(); + // Initialize a map of preimages. + let mut state_preimages = HashMap::new(); + // 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 +651,19 @@ where .or_insert_with(|| HashedStorage::new(account.status.was_destroyed())); if let Some(account) = account.account { + if include_preimages { + state_preimages + .insert(hashed_address, alloy_rlp::encode(address).into()); + } + 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); + + if include_preimages { + state_preimages.insert(hashed_slot, alloy_rlp::encode(slot).into()); + } } } } @@ -659,7 +674,11 @@ where let witness = state_provider .witness(HashedPostState::default(), hashed_state) .map_err(Into::into)?; - Ok(witness) + + Ok(ExecutionWitness { + witness, + state_preimages: include_preimages.then_some(state_preimages), + }) }) .await } @@ -931,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`