reth_optimism_rpc/
witness.rs

1//! Support for optimism specific witness RPCs.
2
3use alloy_primitives::B256;
4use alloy_rpc_types_debug::ExecutionWitness;
5use jsonrpsee_core::{async_trait, RpcResult};
6use reth_chainspec::ChainSpecProvider;
7use reth_evm::ConfigureEvm;
8use reth_node_api::{BuildNextEnv, NodePrimitives};
9use reth_optimism_forks::OpHardforks;
10use reth_optimism_payload_builder::{OpAttributes, OpPayloadBuilder, OpPayloadPrimitives};
11use reth_optimism_txpool::OpPooledTx;
12use reth_primitives_traits::{SealedHeader, TxTy};
13pub use reth_rpc_api::DebugExecutionWitnessApiServer;
14use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult};
15use reth_storage_api::{
16    errors::{ProviderError, ProviderResult},
17    BlockReaderIdExt, NodePrimitivesProvider, StateProviderFactory,
18};
19use reth_tasks::TaskSpawner;
20use reth_transaction_pool::TransactionPool;
21use std::{fmt::Debug, sync::Arc};
22use tokio::sync::{oneshot, Semaphore};
23
24/// An extension to the `debug_` namespace of the RPC API.
25pub struct OpDebugWitnessApi<Pool, Provider, EvmConfig, Attrs> {
26    inner: Arc<OpDebugWitnessApiInner<Pool, Provider, EvmConfig, Attrs>>,
27}
28
29impl<Pool, Provider, EvmConfig, Attrs> OpDebugWitnessApi<Pool, Provider, EvmConfig, Attrs> {
30    /// Creates a new instance of the `OpDebugWitnessApi`.
31    pub fn new(
32        provider: Provider,
33        task_spawner: Box<dyn TaskSpawner>,
34        builder: OpPayloadBuilder<Pool, Provider, EvmConfig, (), Attrs>,
35    ) -> Self {
36        let semaphore = Arc::new(Semaphore::new(3));
37        let inner = OpDebugWitnessApiInner { provider, builder, task_spawner, semaphore };
38        Self { inner: Arc::new(inner) }
39    }
40}
41
42impl<Pool, Provider, EvmConfig, Attrs> OpDebugWitnessApi<Pool, Provider, EvmConfig, Attrs>
43where
44    EvmConfig: ConfigureEvm,
45    Provider: NodePrimitivesProvider<Primitives: NodePrimitives<BlockHeader = Provider::Header>>
46        + BlockReaderIdExt,
47{
48    /// Fetches the parent header by hash.
49    fn parent_header(
50        &self,
51        parent_block_hash: B256,
52    ) -> ProviderResult<SealedHeader<Provider::Header>> {
53        self.inner
54            .provider
55            .sealed_header_by_hash(parent_block_hash)?
56            .ok_or_else(|| ProviderError::HeaderNotFound(parent_block_hash.into()))
57    }
58}
59
60#[async_trait]
61impl<Pool, Provider, EvmConfig, Attrs> DebugExecutionWitnessApiServer<Attrs::RpcPayloadAttributes>
62    for OpDebugWitnessApi<Pool, Provider, EvmConfig, Attrs>
63where
64    Pool: TransactionPool<
65            Transaction: OpPooledTx<Consensus = <Provider::Primitives as NodePrimitives>::SignedTx>,
66        > + 'static,
67    Provider: BlockReaderIdExt<Header = <Provider::Primitives as NodePrimitives>::BlockHeader>
68        + NodePrimitivesProvider<Primitives: OpPayloadPrimitives>
69        + StateProviderFactory
70        + ChainSpecProvider<ChainSpec: OpHardforks>
71        + Clone
72        + 'static,
73    EvmConfig: ConfigureEvm<
74            Primitives = Provider::Primitives,
75            NextBlockEnvCtx: BuildNextEnv<Attrs, Provider::Header, Provider::ChainSpec>,
76        > + 'static,
77    Attrs: OpAttributes<Transaction = TxTy<EvmConfig::Primitives>>,
78{
79    async fn execute_payload(
80        &self,
81        parent_block_hash: B256,
82        attributes: Attrs::RpcPayloadAttributes,
83    ) -> RpcResult<ExecutionWitness> {
84        let _permit = self.inner.semaphore.acquire().await;
85
86        let parent_header = self.parent_header(parent_block_hash).to_rpc_result()?;
87
88        let (tx, rx) = oneshot::channel();
89        let this = self.clone();
90        self.inner.task_spawner.spawn_blocking(Box::pin(async move {
91            let res = this.inner.builder.payload_witness(parent_header, attributes);
92            let _ = tx.send(res);
93        }));
94
95        rx.await
96            .map_err(|err| internal_rpc_err(err.to_string()))?
97            .map_err(|err| internal_rpc_err(err.to_string()))
98    }
99}
100
101impl<Pool, Provider, EvmConfig, Attrs> Clone
102    for OpDebugWitnessApi<Pool, Provider, EvmConfig, Attrs>
103{
104    fn clone(&self) -> Self {
105        Self { inner: Arc::clone(&self.inner) }
106    }
107}
108impl<Pool, Provider, EvmConfig, Attrs> Debug
109    for OpDebugWitnessApi<Pool, Provider, EvmConfig, Attrs>
110{
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        f.debug_struct("OpDebugWitnessApi").finish_non_exhaustive()
113    }
114}
115
116struct OpDebugWitnessApiInner<Pool, Provider, EvmConfig, Attrs> {
117    provider: Provider,
118    builder: OpPayloadBuilder<Pool, Provider, EvmConfig, (), Attrs>,
119    task_spawner: Box<dyn TaskSpawner>,
120    semaphore: Arc<Semaphore>,
121}