//! Support for optimism specific witness RPCs. use alloy_primitives::B256; use alloy_rpc_types_debug::ExecutionWitness; use jsonrpsee_core::{async_trait, RpcResult}; use op_alloy_rpc_types_engine::OpPayloadAttributes; use reth_chainspec::ChainSpecProvider; use reth_evm::{ConfigureEvm, ConfigureEvmFor}; use reth_node_api::NodePrimitives; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_payload_builder::{OpPayloadBuilder, OpPayloadPrimitives}; use reth_primitives::SealedHeader; use reth_provider::{ BlockReaderIdExt, NodePrimitivesProvider, ProviderError, ProviderResult, StateProviderFactory, }; pub use reth_rpc_api::DebugExecutionWitnessApiServer; use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; use reth_tasks::TaskSpawner; use reth_transaction_pool::{PoolTransaction, TransactionPool}; use std::{fmt::Debug, sync::Arc}; use tokio::sync::{oneshot, Semaphore}; /// 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, task_spawner: Box, builder: OpPayloadBuilder, ) -> Self { let semaphore = Arc::new(Semaphore::new(3)); let inner = OpDebugWitnessApiInner { provider, builder, task_spawner, semaphore }; Self { inner: Arc::new(inner) } } } impl OpDebugWitnessApi where EvmConfig: ConfigureEvm, Provider: NodePrimitivesProvider + 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())) } } #[async_trait] impl DebugExecutionWitnessApiServer for OpDebugWitnessApi where Pool: TransactionPool< Transaction: PoolTransaction< Consensus = ::SignedTx, >, > + 'static, Provider: BlockReaderIdExt
+ NodePrimitivesProvider + StateProviderFactory + ChainSpecProvider + Clone + 'static, EvmConfig: ConfigureEvmFor + 'static, { async fn execute_payload( &self, parent_block_hash: B256, attributes: OpPayloadAttributes, ) -> RpcResult { let _permit = self.inner.semaphore.acquire().await; let parent_header = self.parent_header(parent_block_hash).to_rpc_result()?; let (tx, rx) = oneshot::channel(); let this = self.clone(); self.inner.task_spawner.spawn_blocking(Box::pin(async move { let res = this.inner.builder.payload_witness(parent_header, attributes); let _ = tx.send(res); })); rx.await .map_err(|err| internal_rpc_err(err.to_string()))? .map_err(|err| internal_rpc_err(err.to_string())) } } impl Clone for OpDebugWitnessApi where EvmConfig: ConfigureEvm, Provider: NodePrimitivesProvider, { fn clone(&self) -> Self { Self { inner: Arc::clone(&self.inner) } } } impl Debug for OpDebugWitnessApi where EvmConfig: ConfigureEvm, Provider: NodePrimitivesProvider, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("OpDebugWitnessApi").finish_non_exhaustive() } } struct OpDebugWitnessApiInner { provider: Provider, builder: OpPayloadBuilder, task_spawner: Box, semaphore: Arc, }