use crate::{ HlBlock, HlPrimitives, chainspec::HlChainSpec, node::{evm::apply_precompiles, types::HlExtras}, }; use alloy_eips::BlockId; use alloy_evm::Evm; use alloy_network::Ethereum; use alloy_primitives::U256; use reth::{ api::{FullNodeTypes, HeaderTy, NodeTypes, PrimitivesTy}, builder::{ FullNodeComponents, rpc::{EthApiBuilder, EthApiCtx}, }, rpc::{ eth::{DevSigner, FullEthApiServer, core::EthApiInner}, server_types::eth::{ EthApiError, EthStateCache, FeeHistoryCache, GasPriceOracle, receipt::EthReceiptConverter, }, }, tasks::{ TaskSpawner, pool::{BlockingTaskGuard, BlockingTaskPool}, }, }; use reth_evm::{ConfigureEvm, Database, EvmEnvFor, HaltReasonFor, InspectorFor, TxEnvFor}; use reth_primitives::NodePrimitives; use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, ProviderError, ProviderHeader, ProviderTx, }; use reth_rpc::RpcTypes; use reth_rpc_eth_api::{ EthApiTypes, FromEvmError, RpcConvert, RpcConverter, RpcNodeCore, RpcNodeCoreExt, SignableTxRequest, helpers::{ AddDevSigners, EthApiSpec, EthFees, EthState, LoadFee, LoadPendingBlock, LoadState, SpawnBlocking, Trace, pending_block::BuildPendingEnv, spec::SignersForApi, }, }; use revm::context::result::ResultAndState; use std::{fmt, marker::PhantomData, sync::Arc}; mod block; mod call; pub mod engine_api; mod estimate; pub mod precompile; mod transaction; pub trait HlRpcNodeCore: RpcNodeCore> {} /// Container type `HlEthApi` pub(crate) struct HlEthApiInner { /// Gateway to node's core components. pub(crate) eth_api: EthApiInner, } type HlRpcConvert = RpcConverter::Evm, EthReceiptConverter>; pub struct HlEthApi { /// Gateway to node's core components. pub(crate) inner: Arc>, } impl Clone for HlEthApi { fn clone(&self) -> Self { Self { inner: self.inner.clone() } } } impl fmt::Debug for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("HlEthApi").finish_non_exhaustive() } } impl EthApiTypes for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { type Error = EthApiError; type NetworkTypes = Rpc::Network; type RpcConvert = Rpc; fn tx_resp_builder(&self) -> &Self::RpcConvert { self.inner.eth_api.tx_resp_builder() } } impl RpcNodeCore for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { type Primitives = N::Primitives; type Provider = N::Provider; type Pool = N::Pool; type Evm = N::Evm; type Network = N::Network; #[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 provider(&self) -> &Self::Provider { self.inner.eth_api.provider() } } impl RpcNodeCoreExt for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { #[inline] fn cache(&self) -> &EthStateCache { self.inner.eth_api.cache() } } impl EthApiSpec for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { type Transaction = ProviderTx; type Rpc = Rpc::Network; #[inline] fn starting_block(&self) -> U256 { self.inner.eth_api.starting_block() } #[inline] fn signers(&self) -> &SignersForApi { self.inner.eth_api.signers() } } impl SpawnBlocking for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { #[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 LoadFee for HlEthApi where N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { #[inline] fn gas_oracle(&self) -> &GasPriceOracle { self.inner.eth_api.gas_oracle() } #[inline] fn fee_history_cache(&self) -> &FeeHistoryCache> { self.inner.eth_api.fee_history_cache() } } impl LoadState for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, Self: LoadPendingBlock, { } impl EthState for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, Self: LoadPendingBlock, { #[inline] fn max_proof_window(&self) -> u64 { self.inner.eth_api.eth_proof_window() } } impl EthFees for HlEthApi where N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { } impl Trace for HlEthApi where N: HlRpcNodeCore, EthApiError: FromEvmError, Rpc: RpcConvert, { fn inspect( &self, db: DB, evm_env: EvmEnvFor, tx_env: TxEnvFor, inspector: I, ) -> Result>, Self::Error> where DB: Database, I: InspectorFor, { let block_number = evm_env.block_env().number; let hl_extras = self.get_hl_extras(block_number.to::().into())?; let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector); apply_precompiles(&mut evm, &hl_extras); evm.transact(tx_env).map_err(Self::Error::from_evm_err) } } impl HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert, { fn get_hl_extras(&self, block: BlockId) -> Result { Ok(self .provider() .block_by_id(block)? .map(|block| HlExtras { read_precompile_calls: block.body.read_precompile_calls.clone(), highest_precompile_address: block.body.highest_precompile_address, }) .unwrap_or_default()) } } impl AddDevSigners for HlEthApi where N: HlRpcNodeCore, Rpc: RpcConvert< Network: RpcTypes>>, >, { fn with_dev_accounts(&self) { *self.inner.eth_api.signers().write() = DevSigner::random_signers(20) } } /// Builds [`HlEthApi`] for HL. #[derive(Debug)] #[non_exhaustive] pub struct HlEthApiBuilder { /// Marker for network types. pub(crate) _nt: PhantomData, } impl Default for HlEthApiBuilder { fn default() -> Self { Self { _nt: PhantomData } } } impl EthApiBuilder for HlEthApiBuilder where N: FullNodeComponents> + RpcNodeCore< Primitives = PrimitivesTy, Evm: ConfigureEvm>>, >, NetworkT: RpcTypes, HlRpcConvert: RpcConvert>, HlEthApi>: FullEthApiServer< Provider = ::Provider, Pool = ::Pool, > + AddDevSigners, { type EthApi = HlEthApi>; async fn build_eth_api(self, ctx: EthApiCtx<'_, N>) -> eyre::Result { let provider = FullNodeComponents::provider(ctx.components); let rpc_converter = RpcConverter::new(EthReceiptConverter::::new(provider.chain_spec())); let eth_api = ctx.eth_api_builder().with_rpc_converter(rpc_converter).build_inner(); Ok(HlEthApi { inner: Arc::new(HlEthApiInner { eth_api }) }) } }