mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
357 lines
9.7 KiB
Rust
357 lines
9.7 KiB
Rust
//! OP-Reth `eth_` endpoint implementation.
|
|
|
|
pub mod ext;
|
|
pub mod receipt;
|
|
pub mod transaction;
|
|
|
|
mod block;
|
|
mod call;
|
|
mod pending_block;
|
|
|
|
pub use receipt::{OpReceiptBuilder, OpReceiptFieldsBuilder};
|
|
|
|
use alloy_primitives::U256;
|
|
use op_alloy_network::Optimism;
|
|
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
|
use reth_evm::ConfigureEvm;
|
|
use reth_network_api::NetworkInfo;
|
|
use reth_node_api::NodePrimitives;
|
|
use reth_node_builder::EthApiBuilderCtx;
|
|
use reth_optimism_primitives::OpPrimitives;
|
|
use reth_provider::{
|
|
BlockNumReader, BlockReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider,
|
|
NodePrimitivesProvider, ProviderBlock, ProviderHeader, ProviderReceipt, ProviderTx,
|
|
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, FromEvmError, RpcNodeCore, RpcNodeCoreExt,
|
|
};
|
|
use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasPriceOracle};
|
|
use reth_tasks::{
|
|
pool::{BlockingTaskGuard, BlockingTaskPool},
|
|
TaskSpawner,
|
|
};
|
|
use reth_transaction_pool::TransactionPool;
|
|
use std::{fmt, sync::Arc};
|
|
|
|
use crate::{OpEthApiError, SequencerClient};
|
|
|
|
/// Adapter for [`EthApiInner`], which holds all the data required to serve core `eth_` API.
|
|
pub type EthApiNodeBackend<N> = EthApiInner<
|
|
<N as RpcNodeCore>::Provider,
|
|
<N as RpcNodeCore>::Pool,
|
|
<N as RpcNodeCore>::Network,
|
|
<N as RpcNodeCore>::Evm,
|
|
>;
|
|
|
|
/// A helper trait with requirements for [`RpcNodeCore`] to be used in [`OpEthApi`].
|
|
pub trait OpNodeCore: RpcNodeCore<Provider: BlockReader> {}
|
|
impl<T> OpNodeCore for T where T: RpcNodeCore<Provider: BlockReader> {}
|
|
|
|
/// OP-Reth `Eth` API implementation.
|
|
///
|
|
/// This type provides the functionality for handling `eth_` related requests.
|
|
///
|
|
/// This wraps a default `Eth` implementation, and provides additional functionality where the
|
|
/// optimism spec deviates from the default (ethereum) spec, e.g. transaction forwarding to the
|
|
/// sequencer, receipts, additional RPC fields for transaction receipts.
|
|
///
|
|
/// This type implements the [`FullEthApi`](reth_rpc_eth_api::helpers::FullEthApi) by implemented
|
|
/// all the `Eth` helper traits and prerequisite traits.
|
|
#[derive(Clone)]
|
|
pub struct OpEthApi<N: OpNodeCore> {
|
|
/// Gateway to node's core components.
|
|
inner: Arc<OpEthApiInner<N>>,
|
|
}
|
|
|
|
impl<N> OpEthApi<N>
|
|
where
|
|
N: OpNodeCore<
|
|
Provider: BlockReaderIdExt
|
|
+ ChainSpecProvider
|
|
+ CanonStateSubscriptions<Primitives = OpPrimitives>
|
|
+ Clone
|
|
+ 'static,
|
|
>,
|
|
{
|
|
/// Returns a reference to the [`EthApiNodeBackend`].
|
|
pub fn eth_api(&self) -> &EthApiNodeBackend<N> {
|
|
self.inner.eth_api()
|
|
}
|
|
|
|
/// Returns the configured sequencer client, if any.
|
|
pub fn sequencer_client(&self) -> Option<&SequencerClient> {
|
|
self.inner.sequencer_client()
|
|
}
|
|
|
|
/// Build a [`OpEthApi`] using [`OpEthApiBuilder`].
|
|
pub const fn builder() -> OpEthApiBuilder {
|
|
OpEthApiBuilder::new()
|
|
}
|
|
}
|
|
|
|
impl<N> EthApiTypes for OpEthApi<N>
|
|
where
|
|
Self: Send + Sync,
|
|
N: OpNodeCore,
|
|
{
|
|
type Error = OpEthApiError;
|
|
type NetworkTypes = Optimism;
|
|
type TransactionCompat = Self;
|
|
|
|
fn tx_resp_builder(&self) -> &Self::TransactionCompat {
|
|
self
|
|
}
|
|
}
|
|
|
|
impl<N> RpcNodeCore for OpEthApi<N>
|
|
where
|
|
N: OpNodeCore,
|
|
{
|
|
type Provider = N::Provider;
|
|
type Pool = N::Pool;
|
|
type Evm = <N as RpcNodeCore>::Evm;
|
|
type Network = <N as RpcNodeCore>::Network;
|
|
type PayloadBuilder = ();
|
|
|
|
#[inline]
|
|
fn pool(&self) -> &Self::Pool {
|
|
self.inner.eth_api.pool()
|
|
}
|
|
|
|
#[inline]
|
|
fn evm_config(&self) -> &Self::Evm {
|
|
self.inner.eth_api.evm_config()
|
|
}
|
|
|
|
#[inline]
|
|
fn network(&self) -> &Self::Network {
|
|
self.inner.eth_api.network()
|
|
}
|
|
|
|
#[inline]
|
|
fn payload_builder(&self) -> &Self::PayloadBuilder {
|
|
&()
|
|
}
|
|
|
|
#[inline]
|
|
fn provider(&self) -> &Self::Provider {
|
|
self.inner.eth_api.provider()
|
|
}
|
|
}
|
|
|
|
impl<N> RpcNodeCoreExt for OpEthApi<N>
|
|
where
|
|
N: OpNodeCore,
|
|
{
|
|
#[inline]
|
|
fn cache(&self) -> &EthStateCache<ProviderBlock<N::Provider>, ProviderReceipt<N::Provider>> {
|
|
self.inner.eth_api.cache()
|
|
}
|
|
}
|
|
|
|
impl<N> EthApiSpec for OpEthApi<N>
|
|
where
|
|
N: OpNodeCore<
|
|
Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>
|
|
+ BlockNumReader
|
|
+ StageCheckpointReader,
|
|
Network: NetworkInfo,
|
|
>,
|
|
{
|
|
type Transaction = ProviderTx<Self::Provider>;
|
|
|
|
#[inline]
|
|
fn starting_block(&self) -> U256 {
|
|
self.inner.eth_api.starting_block()
|
|
}
|
|
|
|
#[inline]
|
|
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner<ProviderTx<Self::Provider>>>>> {
|
|
self.inner.eth_api.signers()
|
|
}
|
|
}
|
|
|
|
impl<N> SpawnBlocking for OpEthApi<N>
|
|
where
|
|
Self: Send + Sync + Clone + 'static,
|
|
N: OpNodeCore,
|
|
{
|
|
#[inline]
|
|
fn io_task_spawner(&self) -> impl TaskSpawner {
|
|
self.inner.eth_api.task_spawner()
|
|
}
|
|
|
|
#[inline]
|
|
fn tracing_task_pool(&self) -> &BlockingTaskPool {
|
|
self.inner.eth_api.blocking_task_pool()
|
|
}
|
|
|
|
#[inline]
|
|
fn tracing_task_guard(&self) -> &BlockingTaskGuard {
|
|
self.inner.eth_api.blocking_task_guard()
|
|
}
|
|
}
|
|
|
|
impl<N> LoadFee for OpEthApi<N>
|
|
where
|
|
Self: LoadBlock<Provider = N::Provider>,
|
|
N: OpNodeCore<
|
|
Provider: BlockReaderIdExt
|
|
+ ChainSpecProvider<ChainSpec: EthChainSpec + EthereumHardforks>
|
|
+ StateProviderFactory,
|
|
>,
|
|
{
|
|
#[inline]
|
|
fn gas_oracle(&self) -> &GasPriceOracle<Self::Provider> {
|
|
self.inner.eth_api.gas_oracle()
|
|
}
|
|
|
|
#[inline]
|
|
fn fee_history_cache(&self) -> &FeeHistoryCache {
|
|
self.inner.eth_api.fee_history_cache()
|
|
}
|
|
}
|
|
|
|
impl<N> LoadState for OpEthApi<N> where
|
|
N: OpNodeCore<
|
|
Provider: StateProviderFactory + ChainSpecProvider<ChainSpec: EthereumHardforks>,
|
|
Pool: TransactionPool,
|
|
>
|
|
{
|
|
}
|
|
|
|
impl<N> EthState for OpEthApi<N>
|
|
where
|
|
Self: LoadState + SpawnBlocking,
|
|
N: OpNodeCore,
|
|
{
|
|
#[inline]
|
|
fn max_proof_window(&self) -> u64 {
|
|
self.inner.eth_api.eth_proof_window()
|
|
}
|
|
}
|
|
|
|
impl<N> EthFees for OpEthApi<N>
|
|
where
|
|
Self: LoadFee,
|
|
N: OpNodeCore,
|
|
{
|
|
}
|
|
|
|
impl<N> Trace for OpEthApi<N>
|
|
where
|
|
Self: RpcNodeCore<Provider: BlockReader>
|
|
+ LoadState<
|
|
Evm: ConfigureEvm<
|
|
Header = ProviderHeader<Self::Provider>,
|
|
Transaction = ProviderTx<Self::Provider>,
|
|
>,
|
|
Error: FromEvmError<Self::Evm>,
|
|
>,
|
|
N: OpNodeCore,
|
|
{
|
|
}
|
|
|
|
impl<N> AddDevSigners for OpEthApi<N>
|
|
where
|
|
N: OpNodeCore,
|
|
{
|
|
fn with_dev_accounts(&self) {
|
|
*self.inner.eth_api.signers().write() = DevSigner::random_signers(20)
|
|
}
|
|
}
|
|
|
|
impl<N: OpNodeCore> fmt::Debug for OpEthApi<N> {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("OpEthApi").finish_non_exhaustive()
|
|
}
|
|
}
|
|
|
|
/// Container type `OpEthApi`
|
|
#[allow(missing_debug_implementations)]
|
|
struct OpEthApiInner<N: OpNodeCore> {
|
|
/// Gateway to node's core components.
|
|
eth_api: EthApiNodeBackend<N>,
|
|
/// Sequencer client, configured to forward submitted transactions to sequencer of given OP
|
|
/// network.
|
|
sequencer_client: Option<SequencerClient>,
|
|
}
|
|
|
|
impl<N: OpNodeCore> OpEthApiInner<N> {
|
|
/// Returns a reference to the [`EthApiNodeBackend`].
|
|
const fn eth_api(&self) -> &EthApiNodeBackend<N> {
|
|
&self.eth_api
|
|
}
|
|
|
|
/// Returns the configured sequencer client, if any.
|
|
const fn sequencer_client(&self) -> Option<&SequencerClient> {
|
|
self.sequencer_client.as_ref()
|
|
}
|
|
}
|
|
|
|
/// A type that knows how to build a [`OpEthApi`].
|
|
#[derive(Debug, Default)]
|
|
pub struct OpEthApiBuilder {
|
|
/// Sequencer client, configured to forward submitted transactions to sequencer of given OP
|
|
/// network.
|
|
sequencer_client: Option<SequencerClient>,
|
|
}
|
|
|
|
impl OpEthApiBuilder {
|
|
/// Creates a [`OpEthApiBuilder`] instance from [`EthApiBuilderCtx`].
|
|
pub const fn new() -> Self {
|
|
Self { sequencer_client: None }
|
|
}
|
|
|
|
/// With a [`SequencerClient`].
|
|
pub fn with_sequencer(mut self, sequencer_client: Option<SequencerClient>) -> Self {
|
|
self.sequencer_client = sequencer_client;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl OpEthApiBuilder {
|
|
/// Builds an instance of [`OpEthApi`]
|
|
pub fn build<N>(self, ctx: &EthApiBuilderCtx<N>) -> OpEthApi<N>
|
|
where
|
|
N: OpNodeCore<
|
|
Provider: BlockReaderIdExt<
|
|
Block = <<N::Provider as NodePrimitivesProvider>::Primitives as NodePrimitives>::Block,
|
|
Receipt = <<N::Provider as NodePrimitivesProvider>::Primitives as NodePrimitives>::Receipt,
|
|
> + ChainSpecProvider
|
|
+ CanonStateSubscriptions
|
|
+ Clone
|
|
+ 'static,
|
|
>,
|
|
{
|
|
let blocking_task_pool =
|
|
BlockingTaskPool::build().expect("failed to build blocking task pool");
|
|
|
|
let eth_api = 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(),
|
|
Box::new(ctx.executor.clone()),
|
|
ctx.config.proof_permits,
|
|
);
|
|
|
|
OpEthApi {
|
|
inner: Arc::new(OpEthApiInner { eth_api, sequencer_client: self.sequencer_client }),
|
|
}
|
|
}
|
|
}
|