pub mod receipt;
pub mod transaction;
mod block;
mod call;
mod pending_block;
pub use receipt::{OpReceiptBuilder, OpReceiptFieldsBuilder};
use std::{fmt, sync::Arc};
use alloy_primitives::U256;
use op_alloy_network::AnyNetwork;
use reth_chainspec::ChainSpec;
use reth_evm::ConfigureEvm;
use reth_network_api::NetworkInfo;
use reth_node_api::{BuilderProvider, FullNodeComponents, FullNodeTypes, NodeTypes};
use reth_node_builder::EthApiBuilderCtx;
use reth_primitives::Header;
use reth_provider::{
BlockIdReader, BlockNumReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider,
HeaderProvider, StageCheckpointReader, StateProviderFactory,
};
use reth_rpc::eth::{core::EthApiInner, DevSigner};
use reth_rpc_eth_api::{
helpers::{
AddDevSigners, EthApiSpec, EthFees, EthSigner, EthState, LoadBlock, LoadFee, LoadState,
SpawnBlocking, Trace,
},
EthApiTypes,
};
use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasPriceOracle};
use reth_tasks::{
pool::{BlockingTaskGuard, BlockingTaskPool},
TaskSpawner,
};
use reth_transaction_pool::TransactionPool;
use tokio::sync::OnceCell;
use crate::{OpEthApiError, SequencerClient};
pub type EthApiNodeBackend<N> = EthApiInner<
<N as FullNodeTypes>::Provider,
<N as FullNodeComponents>::Pool,
<N as FullNodeComponents>::Network,
<N as FullNodeComponents>::Evm,
>;
#[derive(Clone)]
pub struct OpEthApi<N: FullNodeComponents> {
inner: Arc<EthApiNodeBackend<N>>,
sequencer_client: OnceCell<SequencerClient>,
}
impl<N> OpEthApi<N>
where
N: FullNodeComponents<
Provider: BlockReaderIdExt + ChainSpecProvider + CanonStateSubscriptions + Clone + 'static,
>,
{
#[allow(clippy::type_complexity)]
pub fn with_spawner(ctx: &EthApiBuilderCtx<N>) -> Self {
let blocking_task_pool =
BlockingTaskPool::build().expect("failed to build blocking task pool");
let inner = EthApiInner::new(
ctx.provider.clone(),
ctx.pool.clone(),
ctx.network.clone(),
ctx.cache.clone(),
ctx.new_gas_price_oracle(),
ctx.config.rpc_gas_cap,
ctx.config.rpc_max_simulate_blocks,
ctx.config.eth_proof_window,
blocking_task_pool,
ctx.new_fee_history_cache(),
ctx.evm_config.clone(),
ctx.executor.clone(),
ctx.config.proof_permits,
);
Self { inner: Arc::new(inner), sequencer_client: OnceCell::new() }
}
}
impl<N> EthApiTypes for OpEthApi<N>
where
Self: Send + Sync,
N: FullNodeComponents,
{
type Error = OpEthApiError;
type NetworkTypes = AnyNetwork;
}
impl<N> EthApiSpec for OpEthApi<N>
where
Self: Send + Sync,
N: FullNodeComponents<Types: NodeTypes<ChainSpec = ChainSpec>>,
{
#[inline]
fn provider(
&self,
) -> impl ChainSpecProvider<ChainSpec = ChainSpec> + BlockNumReader + StageCheckpointReader
{
self.inner.provider()
}
#[inline]
fn network(&self) -> impl NetworkInfo {
self.inner.network()
}
#[inline]
fn starting_block(&self) -> U256 {
self.inner.starting_block()
}
#[inline]
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner>>> {
self.inner.signers()
}
}
impl<N> SpawnBlocking for OpEthApi<N>
where
Self: Send + Sync + Clone + 'static,
N: FullNodeComponents,
{
#[inline]
fn io_task_spawner(&self) -> impl TaskSpawner {
self.inner.task_spawner()
}
#[inline]
fn tracing_task_pool(&self) -> &BlockingTaskPool {
self.inner.blocking_task_pool()
}
#[inline]
fn tracing_task_guard(&self) -> &BlockingTaskGuard {
self.inner.blocking_task_guard()
}
}
impl<N> LoadFee for OpEthApi<N>
where
Self: LoadBlock,
N: FullNodeComponents<Types: NodeTypes<ChainSpec = ChainSpec>>,
{
#[inline]
fn provider(
&self,
) -> impl BlockIdReader + HeaderProvider + ChainSpecProvider<ChainSpec = ChainSpec> {
self.inner.provider()
}
#[inline]
fn cache(&self) -> &EthStateCache {
self.inner.cache()
}
#[inline]
fn gas_oracle(&self) -> &GasPriceOracle<impl BlockReaderIdExt> {
self.inner.gas_oracle()
}
#[inline]
fn fee_history_cache(&self) -> &FeeHistoryCache {
self.inner.fee_history_cache()
}
}
impl<N> LoadState for OpEthApi<N>
where
Self: Send + Sync,
N: FullNodeComponents<Types: NodeTypes<ChainSpec = ChainSpec>>,
{
#[inline]
fn provider(&self) -> impl StateProviderFactory + ChainSpecProvider<ChainSpec = ChainSpec> {
self.inner.provider()
}
#[inline]
fn cache(&self) -> &EthStateCache {
self.inner.cache()
}
#[inline]
fn pool(&self) -> impl TransactionPool {
self.inner.pool()
}
}
impl<N> EthState for OpEthApi<N>
where
Self: LoadState + SpawnBlocking,
N: FullNodeComponents,
{
#[inline]
fn max_proof_window(&self) -> u64 {
self.inner.eth_proof_window()
}
}
impl<N> EthFees for OpEthApi<N>
where
Self: LoadFee,
N: FullNodeComponents,
{
}
impl<N> Trace for OpEthApi<N>
where
Self: LoadState,
N: FullNodeComponents,
{
#[inline]
fn evm_config(&self) -> &impl ConfigureEvm<Header = Header> {
self.inner.evm_config()
}
}
impl<N: FullNodeComponents<Types: NodeTypes<ChainSpec = ChainSpec>>> AddDevSigners for OpEthApi<N> {
fn with_dev_accounts(&self) {
*self.signers().write() = DevSigner::random_signers(20)
}
}
impl<N> BuilderProvider<N> for OpEthApi<N>
where
Self: Send,
N: FullNodeComponents,
{
type Ctx<'a> = &'a EthApiBuilderCtx<N>;
fn builder() -> Box<dyn for<'a> Fn(Self::Ctx<'a>) -> Self + Send> {
Box::new(|ctx| Self::with_spawner(ctx))
}
}
impl<N: FullNodeComponents> fmt::Debug for OpEthApi<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OpEthApi").finish_non_exhaustive()
}
}