feat(rpc): add preimages to execution witness response (#10456)

Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
This commit is contained in:
Alexey Shekhirin
2024-09-02 10:25:38 +01:00
committed by GitHub
parent d59854f1dc
commit ef975f15eb
6 changed files with 46 additions and 8 deletions

11
Cargo.lock generated
View File

@ -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",

View File

@ -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 }

View File

@ -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<HashMap<B256, Bytes>>;
include_preimages: bool,
) -> RpcResult<ExecutionWitness>;
/// 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

View File

@ -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 }

View File

@ -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;

View File

@ -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<HashMap<B256, Bytes>, Eth::Error> {
include_preimages: bool,
) -> Result<ExecutionWitness, Eth::Error> {
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<HashMap<B256, Bytes>> {
include_preimages: bool,
) -> RpcResult<ExecutionWitness> {
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`