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