From b31b1ea288363de9010fa3608be130382625ed14 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 15 Nov 2024 20:44:53 +0100 Subject: [PATCH] feat: add op debug witness api (#12583) Co-authored-by: Federico Gimenez --- Cargo.lock | 5 ++ crates/optimism/rpc/Cargo.toml | 8 ++- crates/optimism/rpc/src/lib.rs | 1 + crates/optimism/rpc/src/witness.rs | 81 ++++++++++++++++++++++++++++++ crates/rpc/rpc-api/src/debug.rs | 8 +-- 5 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 crates/optimism/rpc/src/witness.rs diff --git a/Cargo.lock b/Cargo.lock index 650dc4607..ac3dd4fa9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8395,12 +8395,15 @@ dependencies = [ "alloy-consensus", "alloy-eips", "alloy-primitives", + "alloy-rpc-types-debug", "alloy-rpc-types-eth", "derive_more 1.0.0", + "jsonrpsee-core", "jsonrpsee-types", "op-alloy-consensus", "op-alloy-network", "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", "parking_lot", "reqwest", "reth-chainspec", @@ -8412,9 +8415,11 @@ dependencies = [ "reth-optimism-consensus", "reth-optimism-evm", "reth-optimism-forks", + "reth-optimism-payload-builder", "reth-primitives", "reth-provider", "reth-rpc", + "reth-rpc-api", "reth-rpc-eth-api", "reth-rpc-eth-types", "reth-rpc-server-types", diff --git a/crates/optimism/rpc/Cargo.toml b/crates/optimism/rpc/Cargo.toml index 37b64b774..17fafef70 100644 --- a/crates/optimism/rpc/Cargo.toml +++ b/crates/optimism/rpc/Cargo.toml @@ -22,6 +22,7 @@ reth-rpc-server-types.workspace = true reth-tasks = { workspace = true, features = ["rayon"] } reth-transaction-pool.workspace = true reth-rpc.workspace = true +reth-rpc-api.workspace = true reth-node-api.workspace = true reth-network-api.workspace = true reth-node-builder.workspace = true @@ -31,15 +32,18 @@ reth-chainspec.workspace = true reth-optimism-chainspec.workspace = true reth-optimism-consensus.workspace = true reth-optimism-evm.workspace = true +reth-optimism-payload-builder.workspace = true reth-optimism-forks.workspace = true # ethereum alloy-eips.workspace = true alloy-primitives.workspace = true alloy-rpc-types-eth.workspace = true +alloy-rpc-types-debug.workspace = true alloy-consensus.workspace = true op-alloy-network.workspace = true op-alloy-rpc-types.workspace = true +op-alloy-rpc-types-engine.workspace = true op-alloy-consensus.workspace = true revm.workspace = true @@ -49,6 +53,7 @@ tokio.workspace = true reqwest = { workspace = true, features = ["rustls-tls-native-roots"] } # rpc +jsonrpsee-core.workspace = true jsonrpsee-types.workspace = true serde_json.workspace = true @@ -66,5 +71,6 @@ optimism = [ "reth-primitives/optimism", "reth-provider/optimism", "revm/optimism", - "reth-optimism-consensus/optimism" + "reth-optimism-consensus/optimism", + "reth-optimism-payload-builder/optimism" ] diff --git a/crates/optimism/rpc/src/lib.rs b/crates/optimism/rpc/src/lib.rs index 44d0fa353..0fa0debdf 100644 --- a/crates/optimism/rpc/src/lib.rs +++ b/crates/optimism/rpc/src/lib.rs @@ -13,6 +13,7 @@ pub mod error; pub mod eth; pub mod sequencer; +pub mod witness; pub use error::{OpEthApiError, OpInvalidTransactionError, SequencerClientError}; pub use eth::{OpEthApi, OpReceiptBuilder}; diff --git a/crates/optimism/rpc/src/witness.rs b/crates/optimism/rpc/src/witness.rs new file mode 100644 index 000000000..0521fa902 --- /dev/null +++ b/crates/optimism/rpc/src/witness.rs @@ -0,0 +1,81 @@ +//! Support for optimism specific witness RPCs. + +use alloy_consensus::Header; +use alloy_primitives::B256; +use alloy_rpc_types_debug::ExecutionWitness; +use jsonrpsee_core::RpcResult; +use op_alloy_rpc_types_engine::OpPayloadAttributes; +use reth_chainspec::ChainSpecProvider; +use reth_evm::ConfigureEvm; +use reth_optimism_chainspec::OpChainSpec; +use reth_optimism_payload_builder::OpPayloadBuilder; +use reth_primitives::SealedHeader; +use reth_provider::{BlockReaderIdExt, ProviderError, ProviderResult, StateProviderFactory}; +use reth_rpc_api::DebugExecutionWitnessApiServer; +use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; +use std::{fmt::Debug, sync::Arc}; + +/// An extension to the `debug_` namespace of the RPC API. +pub struct OpDebugWitnessApi { + inner: Arc>, +} + +impl OpDebugWitnessApi { + /// Creates a new instance of the `OpDebugWitnessApi`. + pub fn new(provider: Provider, evm_config: EvmConfig) -> Self { + let builder = OpPayloadBuilder::new(evm_config); + let inner = OpDebugWitnessApiInner { provider, builder }; + Self { inner: Arc::new(inner) } + } +} + +impl OpDebugWitnessApi +where + Provider: BlockReaderIdExt, +{ + /// Fetches the parent header by hash. + fn parent_header(&self, parent_block_hash: B256) -> ProviderResult { + self.inner + .provider + .sealed_header_by_hash(parent_block_hash)? + .ok_or_else(|| ProviderError::HeaderNotFound(parent_block_hash.into())) + } +} + +impl DebugExecutionWitnessApiServer + for OpDebugWitnessApi +where + Provider: BlockReaderIdExt + + StateProviderFactory + + ChainSpecProvider + + 'static, + EvmConfig: ConfigureEvm
+ 'static, +{ + fn execute_payload( + &self, + parent_block_hash: B256, + attributes: OpPayloadAttributes, + ) -> RpcResult { + let parent_header = self.parent_header(parent_block_hash).to_rpc_result()?; + self.inner + .builder + .payload_witness(&self.inner.provider, parent_header, attributes) + .map_err(|err| internal_rpc_err(err.to_string())) + } +} + +impl Clone for OpDebugWitnessApi { + fn clone(&self) -> Self { + Self { inner: Arc::clone(&self.inner) } + } +} +impl Debug for OpDebugWitnessApi { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("OpDebugWitnessApi").finish_non_exhaustive() + } +} + +struct OpDebugWitnessApiInner { + provider: Provider, + builder: OpPayloadBuilder, +} diff --git a/crates/rpc/rpc-api/src/debug.rs b/crates/rpc/rpc-api/src/debug.rs index 52b63fe30..28ed9af5c 100644 --- a/crates/rpc/rpc-api/src/debug.rs +++ b/crates/rpc/rpc-api/src/debug.rs @@ -399,10 +399,10 @@ pub trait DebugExecutionWitnessApi { /// hashed trie nodes to their preimages that were required during the execution of the block, /// including during state root recomputation. /// - /// The first argument is the block number or block hash. The second argument is the payload - /// attributes for the new block. The third argument is a list of transactions to be included. - #[method(name = "executePayload")] - async fn execute_payload( + /// The first argument is the parent block hash. The second argument is the payload + /// attributes for the new block. + #[method(name = "executePayload", blocking)] + fn execute_payload( &self, parent_block_hash: B256, attributes: Attributes,