chore(rpc): config network specific transaction type in node builder (#10417)

This commit is contained in:
Emilia Hane
2024-08-22 16:36:38 +02:00
committed by GitHub
parent 7fb9a04337
commit 7d8196e29c
54 changed files with 518 additions and 272 deletions

28
Cargo.lock generated
View File

@ -2856,7 +2856,6 @@ version = "0.0.0"
dependencies = [
"eyre",
"reth",
"reth-chainspec",
"reth-node-ethereum",
"reth-tracing",
"reth-transaction-pool",
@ -5242,6 +5241,20 @@ dependencies = [
"serde",
]
[[package]]
name = "op-alloy-network"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3cbfa664a74fe4577a78d1c4bce18fa93be56756730782283df8ff3241c7118"
dependencies = [
"alloy-consensus",
"alloy-network",
"alloy-primitives",
"alloy-rpc-types-eth",
"op-alloy-consensus",
"op-alloy-rpc-types",
]
[[package]]
name = "op-alloy-rpc-types"
version = "0.1.5"
@ -6948,6 +6961,7 @@ dependencies = [
"eyre",
"futures-util",
"jsonrpsee",
"jsonrpsee-types",
"reth",
"reth-chainspec",
"reth-db",
@ -6959,6 +6973,8 @@ dependencies = [
"reth-provider",
"reth-rpc",
"reth-rpc-layer",
"reth-rpc-types",
"reth-rpc-types-compat",
"reth-stages-types",
"reth-tokio-util",
"reth-tracing",
@ -7684,6 +7700,7 @@ dependencies = [
"reth-payload-builder",
"reth-payload-primitives",
"reth-provider",
"reth-rpc-eth-api",
"reth-tasks",
"reth-transaction-pool",
]
@ -7692,6 +7709,7 @@ dependencies = [
name = "reth-node-builder"
version = "1.0.5"
dependencies = [
"alloy-network",
"aquamarine",
"eyre",
"fdlimit",
@ -7914,6 +7932,7 @@ dependencies = [
"reth-primitives",
"reth-provider",
"reth-revm",
"reth-rpc",
"reth-rpc-eth-api",
"reth-rpc-eth-types",
"reth-rpc-types",
@ -8017,12 +8036,14 @@ dependencies = [
"derive_more 1.0.0",
"jsonrpsee",
"jsonrpsee-types",
"op-alloy-network",
"parking_lot 0.12.3",
"reth-chainspec",
"reth-evm",
"reth-evm-optimism",
"reth-network-api",
"reth-node-api",
"reth-node-builder",
"reth-primitives",
"reth-provider",
"reth-rpc",
@ -8266,6 +8287,7 @@ version = "1.0.5"
dependencies = [
"alloy-dyn-abi",
"alloy-genesis",
"alloy-network",
"alloy-primitives",
"alloy-rlp",
"async-trait",
@ -8321,6 +8343,7 @@ dependencies = [
name = "reth-rpc-api"
version = "1.0.5"
dependencies = [
"alloy-json-rpc",
"jsonrpsee",
"reth-engine-primitives",
"reth-network-peers",
@ -8336,6 +8359,7 @@ version = "1.0.5"
dependencies = [
"futures",
"jsonrpsee",
"jsonrpsee-http-client",
"reth-primitives",
"reth-rpc-api",
"reth-rpc-eth-api",
@ -8429,6 +8453,8 @@ name = "reth-rpc-eth-api"
version = "1.0.5"
dependencies = [
"alloy-dyn-abi",
"alloy-json-rpc",
"alloy-network",
"async-trait",
"auto_impl",
"dyn-clone",

View File

@ -428,6 +428,7 @@ alloy-transport-ws = { version = "0.2.1", default-features = false }
# op
op-alloy-rpc-types = "0.1"
op-alloy-network = "0.1"
# misc
aquamarine = "0.5"

View File

@ -25,7 +25,11 @@ reth-tokio-util.workspace = true
reth-stages-types.workspace = true
reth-network-peers.workspace = true
reth-node-ethereum.workspace = true
reth-rpc-types.workspace = true
reth-rpc-types-compat.workspace = true
# rpc
jsonrpsee-types.workspace = true
jsonrpsee.workspace = true
futures-util.workspace = true

View File

@ -2,6 +2,7 @@
use std::sync::Arc;
use alloy_network::Network;
use node::NodeTestContext;
use reth::{
args::{DiscoveryArgs, NetworkArgs, RpcServerArgs},
@ -51,9 +52,17 @@ pub async fn setup<N>(
) -> eyre::Result<(Vec<NodeHelperType<N, N::AddOns>>, TaskManager, Wallet)>
where
N: Default + Node<TmpNodeAdapter<N>> + NodeTypes<ChainSpec = ChainSpec>,
<<N::ComponentsBuilder as NodeComponentsBuilder<TmpNodeAdapter<N>>>::Components as NodeComponents<TmpNodeAdapter<N>>>::Network: PeersHandleProvider,
<N::AddOns as NodeAddOns<Adapter<N>>>::EthApi:
FullEthApiServer + AddDevSigners + EthApiBuilderProvider<Adapter<N>>,
N::ComponentsBuilder: NodeComponentsBuilder<
TmpNodeAdapter<N>,
Components: NodeComponents<TmpNodeAdapter<N>, Network: PeersHandleProvider>,
>,
N::AddOns: NodeAddOns<
Adapter<N>,
EthApi: FullEthApiServer<
NetworkTypes: Network<TransactionResponse = reth_rpc_types::Transaction>,
> + AddDevSigners
+ EthApiBuilderProvider<Adapter<N>>,
>,
{
let tasks = TaskManager::current();
let exec = tasks.executor();

View File

@ -1,5 +1,6 @@
use std::{marker::PhantomData, pin::Pin};
use alloy_network::Network;
use alloy_rpc_types::BlockNumberOrTag;
use eyre::Ok;
use futures_util::Future;
@ -14,8 +15,7 @@ use reth::{
types::engine::PayloadStatusEnum,
},
};
use reth_chainspec::ChainSpec;
use reth_node_builder::{NodeAddOns, NodeTypes};
use reth_node_builder::{EthApiTypes, NodeAddOns, NodeTypes};
use reth_primitives::{BlockHash, BlockNumber, Bytes, B256};
use reth_stages_types::StageId;
use tokio_stream::StreamExt;
@ -46,7 +46,7 @@ where
impl<Node, AddOns> NodeTestContext<Node, AddOns>
where
Node: FullNodeComponents<ChainSpec = ChainSpec>,
Node: FullNodeComponents,
Node::Network: PeersHandleProvider,
AddOns: NodeAddOns<Node>,
{
@ -93,6 +93,8 @@ where
<Node::Engine as EngineTypes>::ExecutionPayloadV3:
From<<Node::Engine as PayloadTypes>::BuiltPayload> + PayloadEnvelopeExt,
AddOns::EthApi: EthApiSpec + EthTransactions + TraceExt,
<AddOns::EthApi as EthApiTypes>::NetworkTypes:
Network<TransactionResponse = alloy_rpc_types::Transaction>,
{
let mut chain = Vec::with_capacity(length as usize);
for i in 0..length {

View File

@ -1,5 +1,5 @@
use alloy_consensus::TxEnvelope;
use alloy_network::eip2718::Decodable2718;
use alloy_network::{eip2718::Decodable2718, Network};
use reth::{
builder::{rpc::RpcRegistry, FullNodeComponents},
rpc::api::{
@ -7,17 +7,20 @@ use reth::{
DebugApiServer,
},
};
use reth_chainspec::ChainSpec;
use reth_node_builder::EthApiTypes;
use reth_primitives::{Bytes, B256};
#[allow(missing_debug_implementations)]
pub struct RpcTestContext<Node: FullNodeComponents, EthApi> {
pub struct RpcTestContext<Node: FullNodeComponents, EthApi: EthApiTypes> {
pub inner: RpcRegistry<Node, EthApi>,
}
impl<Node: FullNodeComponents<ChainSpec = ChainSpec>, EthApi> RpcTestContext<Node, EthApi>
impl<Node, EthApi> RpcTestContext<Node, EthApi>
where
EthApi: EthApiSpec + EthTransactions + TraceExt,
Node: FullNodeComponents,
EthApi: EthApiSpec
+ EthTransactions<NetworkTypes: Network<TransactionResponse = alloy_rpc_types::Transaction>>
+ TraceExt,
{
/// Injects a raw transaction into the node tx pool via RPC server
pub async fn inject_tx(&self, raw_tx: Bytes) -> Result<B256, EthApi::Error> {

View File

@ -2,13 +2,11 @@ use alloy_consensus::{
BlobTransactionSidecar, EnvKzgSettings, SidecarBuilder, SimpleCoder, TxEip4844Variant,
TxEnvelope,
};
use alloy_network::{eip2718::Encodable2718, EthereumWallet, TransactionBuilder};
use alloy_network::{eip2718::Encodable2718, Ethereum, EthereumWallet, TransactionBuilder};
use alloy_rpc_types::{TransactionInput, TransactionRequest};
use alloy_signer_local::PrivateKeySigner;
use eyre::Ok;
use reth_primitives::{hex, Address, Bytes, U256};
use reth_primitives::B256;
use reth_primitives::{hex, Address, Bytes, TxKind, B256, U256};
/// Helper for transaction operations
#[derive(Debug)]
@ -38,8 +36,11 @@ impl TransactionTestContext {
builder.ingest(b"dummy blob");
let sidecar: BlobTransactionSidecar = builder.build()?;
tx.set_blob_sidecar(sidecar);
tx.set_max_fee_per_blob_gas(15e9 as u128);
<TransactionRequest as TransactionBuilder<Ethereum>>::set_blob_sidecar(&mut tx, sidecar);
<TransactionRequest as TransactionBuilder<Ethereum>>::set_max_fee_per_blob_gas(
&mut tx,
15e9 as u128,
);
let signed = Self::sign_tx(wallet, tx).await;
Ok(signed)
@ -48,7 +49,7 @@ impl TransactionTestContext {
/// Signs an arbitrary [`TransactionRequest`] using the provided wallet
pub async fn sign_tx(wallet: PrivateKeySigner, tx: TransactionRequest) -> TxEnvelope {
let signer = EthereumWallet::from(wallet);
tx.build(&signer).await.unwrap()
<TransactionRequest as TransactionBuilder<Ethereum>>::build(tx, &signer).await.unwrap()
}
/// Creates a tx with blob sidecar and sign it, returning bytes
@ -70,7 +71,11 @@ impl TransactionTestContext {
let l1_block_info = Bytes::from_static(&hex!("7ef9015aa044bae9d41b8380d781187b426c6fe43df5fb2fb57bd4466ef6a701e1f01e015694deaddeaddeaddeaddeaddeaddeaddeaddead000194420000000000000000000000000000000000001580808408f0d18001b90104015d8eb900000000000000000000000000000000000000000000000000000000008057650000000000000000000000000000000000000000000000000000000063d96d10000000000000000000000000000000000000000000000000000000000009f35273d89754a1e0387b89520d989d3be9c37c1f32495a88faf1ea05c61121ab0d1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000002d679b567db6187c0c8323fa982cfb88b74dbcc7000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"));
let tx = tx(chain_id, Some(l1_block_info), nonce);
let signer = EthereumWallet::from(wallet);
tx.build(&signer).await.unwrap().encoded_2718().into()
<TransactionRequest as TransactionBuilder<Ethereum>>::build(tx, &signer)
.await
.unwrap()
.encoded_2718()
.into()
}
/// Validates the sidecar of a given tx envelope and returns the versioned hashes
@ -95,7 +100,7 @@ fn tx(chain_id: u64, data: Option<Bytes>, nonce: u64) -> TransactionRequest {
TransactionRequest {
nonce: Some(nonce),
value: Some(U256::from(100)),
to: Some(reth_primitives::TxKind::Call(Address::random())),
to: Some(TxKind::Call(Address::random())),
gas: Some(210000),
max_fee_per_gas: Some(20e9 as u128),
max_priority_fee_per_gas: Some(20e9 as u128),

View File

@ -47,7 +47,7 @@ impl EthereumNode {
EthereumConsensusBuilder,
>
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
<Node as NodeTypes>::Engine: PayloadTypes<
BuiltPayload = EthBuiltPayload,
PayloadAttributes = EthPayloadAttributes,
@ -105,7 +105,7 @@ pub struct EthereumExecutorBuilder;
impl<Node> ExecutorBuilder<Node> for EthereumExecutorBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type EVM = EthEvmConfig;
type Executor = EthExecutorProvider<Self::EVM>;
@ -134,7 +134,7 @@ pub struct EthereumPoolBuilder {
impl<Node> PoolBuilder<Node> for EthereumPoolBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type Pool = EthTransactionPool<Node::Provider, DiskFileBlobStore>;
@ -212,7 +212,7 @@ impl<EVM> EthereumPayloadBuilder<EVM> {
impl<Node, Evm, Pool> PayloadServiceBuilder<Node, Pool> for EthereumPayloadBuilder<Evm>
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
Evm: ConfigureEvm,
Pool: TransactionPool + Unpin + 'static,
<Node as NodeTypes>::Engine: PayloadTypes<
@ -284,7 +284,7 @@ pub struct EthereumConsensusBuilder {
impl<Node> ConsensusBuilder<Node> for EthereumConsensusBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type Consensus = Arc<dyn reth_consensus::Consensus>;

View File

@ -21,4 +21,5 @@ reth-transaction-pool.workspace = true
reth-payload-builder.workspace = true
reth-payload-primitives.workspace = true
reth-tasks.workspace = true
reth-rpc-eth-api.workspace = true
reth-network-api.workspace = true

View File

@ -26,3 +26,5 @@ pub use node::*;
// re-export for convenience
pub use reth_provider::FullProvider;
pub use reth_rpc_eth_api::EthApiTypes;

View File

@ -2,7 +2,7 @@
use std::marker::PhantomData;
use reth_chainspec::EthChainSpec;
use reth_chainspec::{ChainSpec, EthChainSpec};
use reth_db_api::{
database::Database,
database_metrics::{DatabaseMetadata, DatabaseMetrics},
@ -11,6 +11,7 @@ use reth_evm::execute::BlockExecutorProvider;
use reth_network_api::FullNetwork;
use reth_payload_builder::PayloadBuilderHandle;
use reth_provider::FullProvider;
use reth_rpc_eth_api::EthApiTypes;
use reth_tasks::TaskExecutor;
use reth_transaction_pool::TransactionPool;
@ -64,7 +65,7 @@ where
/// node.
///
/// Its types are configured by node internally and are not intended to be user configurable.
pub trait FullNodeTypes: NodeTypes + 'static {
pub trait FullNodeTypes: NodeTypes<ChainSpec = ChainSpec> + 'static {
/// Underlying database type used by the node to store and retrieve data.
type DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static;
/// The provider type used to interact with the node.
@ -114,7 +115,7 @@ where
impl<Types, DB, Provider> FullNodeTypes for FullNodeTypesAdapter<Types, DB, Provider>
where
Types: NodeTypes,
Types: NodeTypes<ChainSpec = ChainSpec>,
Provider: FullProvider<DB, Types::ChainSpec>,
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
{
@ -162,7 +163,7 @@ pub trait FullNodeComponents: FullNodeTypes + Clone + 'static {
pub trait NodeAddOns<N: FullNodeComponents>: Send + Sync + Unpin + Clone + 'static {
/// The core `eth` namespace API type to install on the RPC server (see
/// `reth_rpc_eth_api::EthApiServer`).
type EthApi: Send + Clone;
type EthApi: EthApiTypes + Send + Clone;
}
impl<N: FullNodeComponents> NodeAddOns<N> for () {

View File

@ -55,6 +55,9 @@ reth-engine-service.workspace = true
reth-tokio-util.workspace = true
reth-engine-tree.workspace = true
## ethereum
alloy-network.workspace = true
## async
futures.workspace = true
tokio = { workspace = true, features = [

View File

@ -2,7 +2,7 @@
use std::marker::PhantomData;
use reth_node_api::{FullNodeComponents, NodeAddOns};
use reth_node_api::{EthApiTypes, FullNodeComponents, NodeAddOns};
use crate::{exex::BoxedLaunchExEx, hooks::NodeHooks, rpc::RpcHooks};
@ -21,7 +21,7 @@ pub struct AddOns<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> {
/// Captures node specific addons that can be installed on top of the type configured node and are
/// required for launching the node, such as RPC.
#[derive(Default)]
pub struct RpcAddOns<Node: FullNodeComponents, EthApi> {
pub struct RpcAddOns<Node: FullNodeComponents, EthApi: EthApiTypes> {
/// Core `eth` API type to install on the RPC server, configured w.r.t. network.
pub _eth_api: PhantomData<EthApi>,
/// Additional RPC hooks.

View File

@ -328,7 +328,11 @@ where
<N::ComponentsBuilder as NodeComponentsBuilder<RethFullAdapter<DB, N>>>::Components,
>
>
+ FullEthApiServer
+ FullEthApiServer<
NetworkTypes: alloy_network::Network<
TransactionResponse = reth_rpc_types::Transaction
>,
>
+ AddDevSigners
>,
{
@ -474,8 +478,9 @@ where
AO: NodeAddOns<
NodeAdapter<RethFullAdapter<DB, T>, CB::Components>,
EthApi: EthApiBuilderProvider<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>
+ FullEthApiServer
+ AddDevSigners,
+ FullEthApiServer<
NetworkTypes: alloy_network::Network<TransactionResponse = reth_rpc_types::Transaction>,
> + AddDevSigners,
>,
{
/// Launches the node with the [`DefaultNodeLauncher`] that sets up engine API consensus and rpc

View File

@ -35,13 +35,11 @@ use tokio::sync::{mpsc::unbounded_channel, oneshot};
use tokio_stream::wrappers::UnboundedReceiverStream;
use crate::{
components::NodeComponents,
hooks::NodeHooks,
launch::{LaunchContext, LaunchNode},
rpc::{launch_rpc_servers, EthApiBuilderProvider},
setup::build_networked_pipeline,
AddOns, ExExLauncher, FullNode, NodeAdapter, NodeBuilderWithComponents, NodeComponentsBuilder,
NodeHandle, NodeTypesAdapter,
AddOns, ExExLauncher, FullNode, LaunchContext, LaunchNode, NodeAdapter,
NodeBuilderWithComponents, NodeComponents, NodeComponentsBuilder, NodeHandle, NodeTypesAdapter,
};
/// The engine node launcher.
@ -68,8 +66,9 @@ where
AO: NodeAddOns<
NodeAdapter<T, CB::Components>,
EthApi: EthApiBuilderProvider<NodeAdapter<T, CB::Components>>
+ FullEthApiServer
+ AddDevSigners,
+ FullEthApiServer<
NetworkTypes: alloy_network::Network<TransactionResponse = reth_rpc_types::Transaction>,
> + AddDevSigners,
>,
{
type Node = NodeHandle<NodeAdapter<T, CB::Components>, AO>;

View File

@ -110,8 +110,9 @@ where
AO: NodeAddOns<
NodeAdapter<T, CB::Components>,
EthApi: EthApiBuilderProvider<NodeAdapter<T, CB::Components>>
+ FullEthApiServer
+ AddDevSigners,
+ FullEthApiServer<
NetworkTypes: alloy_network::Network<TransactionResponse = reth_rpc_types::Transaction>,
> + AddDevSigners,
>,
{
type Node = NodeHandle<NodeAdapter<T, CB::Components>, AO>;

View File

@ -6,11 +6,13 @@ use std::{
};
use futures::TryFutureExt;
use reth_chainspec::ChainSpec;
use reth_node_api::{BuilderProvider, FullNodeComponents};
use reth_node_core::{
node_config::NodeConfig,
rpc::{api::EngineApiServer, eth::FullEthApiServer},
rpc::{
api::EngineApiServer,
eth::{EthApiTypes, FullEthApiServer},
},
};
use reth_payload_builder::PayloadBuilderHandle;
use reth_rpc_builder::{
@ -43,13 +45,21 @@ pub struct RpcHooks<Node: FullNodeComponents, EthApi> {
pub extend_rpc_modules: Box<dyn ExtendRpcModules<Node, EthApi>>,
}
impl<Node: FullNodeComponents, EthApi> Default for RpcHooks<Node, EthApi> {
impl<Node, EthApi> Default for RpcHooks<Node, EthApi>
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn default() -> Self {
Self { on_rpc_started: Box::<()>::default(), extend_rpc_modules: Box::<()>::default() }
}
}
impl<Node: FullNodeComponents, EthApi> RpcHooks<Node, EthApi> {
impl<Node, EthApi> RpcHooks<Node, EthApi>
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
/// Sets the hook that is run once the rpc server is started.
pub(crate) fn set_on_rpc_started<F>(&mut self, hook: F) -> &mut Self
where
@ -89,7 +99,11 @@ impl<Node: FullNodeComponents, EthApi> RpcHooks<Node, EthApi> {
}
}
impl<Node: FullNodeComponents, EthApi> fmt::Debug for RpcHooks<Node, EthApi> {
impl<Node, EthApi> fmt::Debug for RpcHooks<Node, EthApi>
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RpcHooks")
.field("on_rpc_started", &"...")
@ -99,7 +113,7 @@ impl<Node: FullNodeComponents, EthApi> fmt::Debug for RpcHooks<Node, EthApi> {
}
/// Event hook that is called once the rpc server is started.
pub trait OnRpcStarted<Node: FullNodeComponents, EthApi>: Send {
pub trait OnRpcStarted<Node: FullNodeComponents, EthApi: EthApiTypes>: Send {
/// The hook that is called once the rpc server is started.
fn on_rpc_started(
self: Box<Self>,
@ -112,6 +126,7 @@ impl<Node, EthApi, F> OnRpcStarted<Node, EthApi> for F
where
F: FnOnce(RpcContext<'_, Node, EthApi>, RethRpcServerHandles) -> eyre::Result<()> + Send,
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn on_rpc_started(
self: Box<Self>,
@ -122,7 +137,11 @@ where
}
}
impl<Node: FullNodeComponents, EthApi> OnRpcStarted<Node, EthApi> for () {
impl<Node, EthApi> OnRpcStarted<Node, EthApi> for ()
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn on_rpc_started(
self: Box<Self>,
_: RpcContext<'_, Node, EthApi>,
@ -133,7 +152,7 @@ impl<Node: FullNodeComponents, EthApi> OnRpcStarted<Node, EthApi> for () {
}
/// Event hook that is called when the rpc server is started.
pub trait ExtendRpcModules<Node: FullNodeComponents, EthApi>: Send {
pub trait ExtendRpcModules<Node: FullNodeComponents, EthApi: EthApiTypes>: Send {
/// The hook that is called once the rpc server is started.
fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()>;
}
@ -142,13 +161,18 @@ impl<Node, EthApi, F> ExtendRpcModules<Node, EthApi> for F
where
F: FnOnce(RpcContext<'_, Node, EthApi>) -> eyre::Result<()> + Send,
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
(*self)(ctx)
}
}
impl<Node: FullNodeComponents, EthApi> ExtendRpcModules<Node, EthApi> for () {
impl<Node, EthApi> ExtendRpcModules<Node, EthApi> for ()
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn extend_rpc_modules(self: Box<Self>, _: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
Ok(())
}
@ -157,7 +181,7 @@ impl<Node: FullNodeComponents, EthApi> ExtendRpcModules<Node, EthApi> for () {
/// Helper wrapper type to encapsulate the [`RpcRegistryInner`] over components trait.
#[derive(Debug, Clone)]
#[allow(clippy::type_complexity)]
pub struct RpcRegistry<Node: FullNodeComponents, EthApi> {
pub struct RpcRegistry<Node: FullNodeComponents, EthApi: EthApiTypes> {
pub(crate) registry: RpcRegistryInner<
Node::Provider,
Node::Pool,
@ -168,7 +192,11 @@ pub struct RpcRegistry<Node: FullNodeComponents, EthApi> {
>,
}
impl<Node: FullNodeComponents, EthApi> Deref for RpcRegistry<Node, EthApi> {
impl<Node, EthApi> Deref for RpcRegistry<Node, EthApi>
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
type Target = RpcRegistryInner<
Node::Provider,
Node::Pool,
@ -183,7 +211,11 @@ impl<Node: FullNodeComponents, EthApi> Deref for RpcRegistry<Node, EthApi> {
}
}
impl<Node: FullNodeComponents, EthApi> DerefMut for RpcRegistry<Node, EthApi> {
impl<Node, EthApi> DerefMut for RpcRegistry<Node, EthApi>
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.registry
}
@ -197,7 +229,7 @@ impl<Node: FullNodeComponents, EthApi> DerefMut for RpcRegistry<Node, EthApi> {
/// transport modules [`TransportRpcModules`] as well as configured authenticated methods
/// [`AuthRpcModule`].
#[allow(missing_debug_implementations)]
pub struct RpcContext<'a, Node: FullNodeComponents, EthApi> {
pub struct RpcContext<'a, Node: FullNodeComponents, EthApi: EthApiTypes> {
/// The node components.
pub(crate) node: Node,
@ -219,7 +251,11 @@ pub struct RpcContext<'a, Node: FullNodeComponents, EthApi> {
pub auth_module: &'a mut AuthRpcModule,
}
impl<'a, Node: FullNodeComponents, EthApi> RpcContext<'a, Node, EthApi> {
impl<'a, Node, EthApi> RpcContext<'a, Node, EthApi>
where
Node: FullNodeComponents,
EthApi: EthApiTypes,
{
/// Returns the config of the node.
pub const fn config(&self) -> &NodeConfig {
self.config
@ -260,9 +296,12 @@ pub async fn launch_rpc_servers<Node, Engine, EthApi>(
add_ons: RpcAddOns<Node, EthApi>,
) -> eyre::Result<(RethRpcServerHandles, RpcRegistry<Node, EthApi>)>
where
EthApi: EthApiBuilderProvider<Node> + FullEthApiServer,
Node: FullNodeComponents<ChainSpec = ChainSpec> + Clone,
Node: FullNodeComponents + Clone,
Engine: EngineApiServer<Node::Engine>,
EthApi: EthApiBuilderProvider<Node>
+ FullEthApiServer<
NetworkTypes: alloy_network::Network<TransactionResponse = reth_rpc_types::Transaction>,
>,
{
let auth_config = config.rpc.auth_server_config(jwt_secret)?;
let module_config = config.rpc.transport_rpc_module_config();
@ -334,7 +373,7 @@ where
}
/// Provides builder for the core `eth` API type.
pub trait EthApiBuilderProvider<N: FullNodeComponents>: BuilderProvider<N> {
pub trait EthApiBuilderProvider<N: FullNodeComponents>: BuilderProvider<N> + EthApiTypes {
/// Returns the eth api builder.
#[allow(clippy::type_complexity)]
fn eth_api_builder() -> Box<dyn Fn(&EthApiBuilderCtx<N>) -> Self + Send>;
@ -343,7 +382,7 @@ pub trait EthApiBuilderProvider<N: FullNodeComponents>: BuilderProvider<N> {
impl<N, F> EthApiBuilderProvider<N> for F
where
N: FullNodeComponents,
for<'a> F: BuilderProvider<N, Ctx<'a> = &'a EthApiBuilderCtx<N>>,
for<'a> F: BuilderProvider<N, Ctx<'a> = &'a EthApiBuilderCtx<N>> + EthApiTypes,
{
fn eth_api_builder() -> Box<dyn Fn(&EthApiBuilderCtx<N>) -> Self + Send> {
F::builder()

View File

@ -36,6 +36,7 @@ reth-discv5.workspace = true
reth-rpc-eth-types.workspace = true
reth-rpc-eth-api.workspace = true
reth-optimism-rpc.workspace = true
reth-rpc.workspace = true
# async
async-trait.workspace = true

View File

@ -119,7 +119,7 @@ pub struct OptimismExecutorBuilder;
impl<Node> ExecutorBuilder<Node> for OptimismExecutorBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type EVM = OptimismEvmConfig;
type Executor = OpExecutorProvider<Self::EVM>;
@ -146,7 +146,7 @@ pub struct OptimismPoolBuilder;
impl<Node> PoolBuilder<Node> for OptimismPoolBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type Pool = OpTransactionPool<Node::Provider, DiskFileBlobStore>;
@ -290,7 +290,7 @@ pub struct OptimismNetworkBuilder {
impl<Node, Pool> NetworkBuilder<Node, Pool> for OptimismNetworkBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
Pool: TransactionPool + Unpin + 'static,
{
async fn build_network(
@ -347,7 +347,7 @@ pub struct OptimismConsensusBuilder;
impl<Node> ConsensusBuilder<Node> for OptimismConsensusBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type Consensus = Arc<dyn reth_consensus::Consensus>;

View File

@ -9,4 +9,4 @@ repository.workspace = true
description = "OP primitive types"
[lints]
workspace = true
workspace = true

View File

@ -26,10 +26,12 @@ reth-transaction-pool.workspace = true
reth-rpc.workspace = true
reth-node-api.workspace = true
reth-network-api.workspace = true
reth-node-builder.workspace = true
reth-chainspec.workspace = true
# ethereum
alloy-primitives.workspace = true
op-alloy-network.workspace = true
revm.workspace = true
# async
@ -60,5 +62,5 @@ optimism = [
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-rpc-eth-api/optimism",
"revm/optimism"
"revm/optimism",
]

View File

@ -1,4 +1,3 @@
use reth_chainspec::ChainSpec;
use reth_evm::ConfigureEvm;
use reth_node_api::FullNodeComponents;
use reth_primitives::{
@ -17,7 +16,7 @@ use crate::{OpEthApi, OpEthApiError};
impl<N> EthCall for OpEthApi<N>
where
Self: Call,
N: FullNodeComponents<ChainSpec = ChainSpec>,
N: FullNodeComponents,
{
}

View File

@ -11,10 +11,12 @@ use std::{fmt, sync::Arc};
use alloy_primitives::U256;
use derive_more::Deref;
use op_alloy_network::Optimism;
use reth_chainspec::ChainSpec;
use reth_evm::ConfigureEvm;
use reth_network_api::NetworkInfo;
use reth_node_api::{BuilderProvider, FullNodeComponents, FullNodeTypes};
use reth_node_builder::EthApiBuilderCtx;
use reth_provider::{
BlockIdReader, BlockNumReader, BlockReaderIdExt, ChainSpecProvider, HeaderProvider,
StageCheckpointReader, StateProviderFactory,
@ -22,15 +24,15 @@ use reth_provider::{
use reth_rpc::eth::{core::EthApiInner, DevSigner};
use reth_rpc_eth_api::{
helpers::{
AddDevSigners, EthApiSpec, EthFees, EthState, LoadBlock, LoadFee, LoadState, SpawnBlocking,
Trace,
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},
TaskExecutor, TaskSpawner,
TaskSpawner,
};
use reth_transaction_pool::TransactionPool;
@ -44,16 +46,6 @@ pub type EthApiNodeBackend<N> = EthApiInner<
<N as FullNodeComponents>::Evm,
>;
/// Adapter for [`EthApiBuilderCtx`].
pub type EthApiBuilderCtx<N> = reth_rpc_eth_types::EthApiBuilderCtx<
<N as FullNodeTypes>::Provider,
<N as FullNodeComponents>::Pool,
<N as FullNodeComponents>::Evm,
<N as FullNodeComponents>::Network,
TaskExecutor,
<N as FullNodeTypes>::Provider,
>;
/// OP-Reth `Eth` API implementation.
///
/// This type provides the functionality for handling `eth_` related requests.
@ -66,6 +58,7 @@ pub type EthApiBuilderCtx<N> = reth_rpc_eth_types::EthApiBuilderCtx<
/// all the `Eth` helper traits and prerequisite traits.
#[derive(Clone, Deref)]
pub struct OpEthApi<N: FullNodeComponents> {
#[deref]
inner: Arc<EthApiNodeBackend<N>>,
}
@ -99,14 +92,16 @@ impl<N: FullNodeComponents> OpEthApi<N> {
impl<N> EthApiTypes for OpEthApi<N>
where
Self: Send + Sync,
N: FullNodeComponents<ChainSpec = ChainSpec>,
N: FullNodeComponents,
{
type Error = OpEthApiError;
type NetworkTypes = Optimism;
}
impl<N> EthApiSpec for OpEthApi<N>
where
N: FullNodeComponents<ChainSpec = ChainSpec>,
Self: Send + Sync,
N: FullNodeComponents,
{
#[inline]
fn provider(
@ -127,7 +122,7 @@ where
}
#[inline]
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn reth_rpc_eth_api::helpers::EthSigner>>> {
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner>>> {
self.inner.signers()
}
}
@ -135,7 +130,7 @@ where
impl<N> SpawnBlocking for OpEthApi<N>
where
Self: Send + Sync + Clone + 'static,
N: FullNodeComponents<ChainSpec = ChainSpec>,
N: FullNodeComponents,
{
#[inline]
fn io_task_spawner(&self) -> impl TaskSpawner {
@ -156,7 +151,7 @@ where
impl<N> LoadFee for OpEthApi<N>
where
Self: LoadBlock,
N: FullNodeComponents<ChainSpec = ChainSpec>,
N: FullNodeComponents,
{
#[inline]
fn provider(
@ -184,7 +179,7 @@ where
impl<N> LoadState for OpEthApi<N>
where
Self: Send + Sync,
N: FullNodeComponents<ChainSpec = ChainSpec>,
N: FullNodeComponents,
{
#[inline]
fn provider(&self) -> impl StateProviderFactory + ChainSpecProvider<ChainSpec = ChainSpec> {
@ -239,6 +234,7 @@ impl<N: FullNodeComponents> AddDevSigners for OpEthApi<N> {
impl<N> BuilderProvider<N> for OpEthApi<N>
where
Self: Send,
N: FullNodeComponents,
{
type Ctx<'a> = &'a EthApiBuilderCtx<N>;
@ -249,7 +245,7 @@ where
}
impl<N: FullNodeComponents> fmt::Debug for OpEthApi<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OpEthApi").finish_non_exhaustive()
}
}

View File

@ -1,6 +1,5 @@
//! Loads OP pending block for a RPC response.
use crate::OpEthApi;
use reth_chainspec::ChainSpec;
use reth_evm::ConfigureEvm;
use reth_node_api::FullNodeComponents;
@ -18,10 +17,12 @@ use reth_rpc_eth_api::{
use reth_rpc_eth_types::{EthApiError, PendingBlock};
use reth_transaction_pool::TransactionPool;
use crate::OpEthApi;
impl<N> LoadPendingBlock for OpEthApi<N>
where
Self: SpawnBlocking,
N: FullNodeComponents<ChainSpec = ChainSpec>,
N: FullNodeComponents,
{
#[inline]
fn provider(

View File

@ -19,6 +19,9 @@ reth-rpc-eth-api.workspace = true
reth-engine-primitives.workspace = true
reth-network-peers.workspace = true
# ethereum
alloy-json-rpc.workspace = true
# misc
jsonrpsee = { workspace = true, features = ["server", "macros"] }

View File

@ -3,6 +3,7 @@
//! This contains the `engine_` namespace and the subset of the `eth_` namespace that is exposed to
//! the consensus client.
use alloy_json_rpc::RpcObject;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_engine_primitives::EngineTypes;
use reth_primitives::{Address, BlockHash, BlockId, BlockNumberOrTag, Bytes, B256, U256, U64};
@ -13,8 +14,8 @@ use reth_rpc_types::{
ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration,
},
state::StateOverride,
BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log, RichBlock,
SyncStatus, TransactionRequest,
BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log, SyncStatus,
TransactionRequest,
};
// NOTE: We can't use associated types in the `EngineApi` trait because of jsonrpsee, so we use a
// generic here. It would be nice if the rpc macro would understand which types need to have serde.
@ -219,7 +220,7 @@ pub trait EngineApi<Engine: EngineTypes> {
/// Specifically for the engine auth server: <https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md#underlying-protocol>
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))]
pub trait EngineEthApi {
pub trait EngineEthApi<T: RpcObject, B: RpcObject> {
/// Returns an object with data about the sync status or false.
#[method(name = "syncing")]
fn syncing(&self) -> RpcResult<SyncStatus>;
@ -248,15 +249,11 @@ pub trait EngineEthApi {
/// Returns information about a block by hash.
#[method(name = "getBlockByHash")]
async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult<Option<RichBlock>>;
async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult<Option<B>>;
/// Returns information about a block by number.
#[method(name = "getBlockByNumber")]
async fn block_by_number(
&self,
number: BlockNumberOrTag,
full: bool,
) -> RpcResult<Option<RichBlock>>;
async fn block_by_number(&self, number: BlockNumberOrTag, full: bool) -> RpcResult<Option<B>>;
/// Sends signed transaction, returning its hash.
#[method(name = "sendRawTransaction")]

View File

@ -28,6 +28,7 @@ reth-tasks = { workspace = true, features = ["rayon"] }
reth-transaction-pool.workspace = true
reth-evm.workspace = true
reth-engine-primitives.workspace = true
reth-rpc-types.workspace = true
# rpc/net
jsonrpsee = { workspace = true, features = ["server"] }

View File

@ -807,7 +807,7 @@ where
/// If called outside of the tokio runtime. See also [`Self::eth_api`]
pub fn register_eth(&mut self) -> &mut Self
where
EthApi: EthApiServer,
EthApi: EthApiServer<reth_rpc_types::Transaction, reth_rpc_types::Block>,
{
let eth_api = self.eth_api().clone();
self.modules.insert(RethRpcModule::Eth, eth_api.into_rpc().into());
@ -821,7 +821,7 @@ where
/// If called outside of the tokio runtime. See also [`Self::eth_api`]
pub fn register_ots(&mut self) -> &mut Self
where
EthApi: EthApiServer + TraceExt,
EthApi: EthApiServer<reth_rpc_types::Transaction, reth_rpc_types::Block> + TraceExt,
{
let otterscan_api = self.otterscan_api();
self.modules.insert(RethRpcModule::Ots, otterscan_api.into_rpc().into());
@ -921,7 +921,7 @@ where
/// If called outside of the tokio runtime. See also [`Self::eth_api`]
pub fn otterscan_api(&self) -> OtterscanApi<EthApi>
where
EthApi: EthApiServer,
EthApi: EthApiServer<reth_rpc_types::Transaction, reth_rpc_types::Block>,
{
let eth_api = self.eth_api().clone();
OtterscanApi::new(eth_api)

View File

@ -116,20 +116,21 @@ async fn test_filter_calls<C>(client: &C)
where
C: ClientT + SubscriptionClientT + Sync,
{
EthFilterApiClient::new_filter(client, Filter::default()).await.unwrap();
EthFilterApiClient::new_pending_transaction_filter(client, None).await.unwrap();
EthFilterApiClient::new_pending_transaction_filter(
EthFilterApiClient::<Transaction>::new_filter(client, Filter::default()).await.unwrap();
EthFilterApiClient::<Transaction>::new_pending_transaction_filter(client, None).await.unwrap();
EthFilterApiClient::<Transaction>::new_pending_transaction_filter(
client,
Some(PendingTransactionFilterKind::Full),
)
.await
.unwrap();
let id = EthFilterApiClient::new_block_filter(client).await.unwrap();
EthFilterApiClient::filter_changes(client, id.clone()).await.unwrap();
EthFilterApiClient::logs(client, Filter::default()).await.unwrap();
let id = EthFilterApiClient::new_filter(client, Filter::default()).await.unwrap();
EthFilterApiClient::filter_logs(client, id.clone()).await.unwrap();
EthFilterApiClient::uninstall_filter(client, id).await.unwrap();
let id = EthFilterApiClient::<Transaction>::new_block_filter(client).await.unwrap();
EthFilterApiClient::<Transaction>::filter_changes(client, id.clone()).await.unwrap();
EthFilterApiClient::<Transaction>::logs(client, Filter::default()).await.unwrap();
let id =
EthFilterApiClient::<Transaction>::new_filter(client, Filter::default()).await.unwrap();
EthFilterApiClient::<Transaction>::filter_logs(client, id.clone()).await.unwrap();
EthFilterApiClient::<Transaction>::uninstall_filter(client, id).await.unwrap();
}
async fn test_basic_admin_calls<C>(client: &C)
@ -172,60 +173,136 @@ where
.unwrap();
// Implemented
EthApiClient::protocol_version(client).await.unwrap();
EthApiClient::chain_id(client).await.unwrap();
EthApiClient::accounts(client).await.unwrap();
EthApiClient::get_account(client, address, block_number.into()).await.unwrap();
EthApiClient::block_number(client).await.unwrap();
EthApiClient::get_code(client, address, None).await.unwrap();
EthApiClient::send_raw_transaction(client, tx).await.unwrap();
EthApiClient::fee_history(client, U64::from(0), block_number, None).await.unwrap();
EthApiClient::balance(client, address, None).await.unwrap();
EthApiClient::transaction_count(client, address, None).await.unwrap();
EthApiClient::storage_at(client, address, U256::default().into(), None).await.unwrap();
EthApiClient::block_by_hash(client, hash, false).await.unwrap();
EthApiClient::block_by_number(client, block_number, false).await.unwrap();
EthApiClient::block_transaction_count_by_number(client, block_number).await.unwrap();
EthApiClient::block_transaction_count_by_hash(client, hash).await.unwrap();
EthApiClient::block_uncles_count_by_hash(client, hash).await.unwrap();
EthApiClient::block_uncles_count_by_number(client, block_number).await.unwrap();
EthApiClient::uncle_by_block_hash_and_index(client, hash, index).await.unwrap();
EthApiClient::uncle_by_block_number_and_index(client, block_number, index).await.unwrap();
EthApiClient::sign(client, address, bytes.clone()).await.unwrap_err();
EthApiClient::sign_typed_data(client, address, typed_data).await.unwrap_err();
EthApiClient::transaction_by_hash(client, tx_hash).await.unwrap();
EthApiClient::transaction_by_block_hash_and_index(client, hash, index).await.unwrap();
EthApiClient::transaction_by_block_number_and_index(client, block_number, index).await.unwrap();
EthApiClient::create_access_list(client, call_request.clone(), Some(block_number.into()))
EthApiClient::<Transaction, RichBlock>::protocol_version(client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::chain_id(client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::accounts(client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::get_account(client, address, block_number.into())
.await
.unwrap();
EthApiClient::estimate_gas(client, call_request.clone(), Some(block_number.into()), None)
EthApiClient::<Transaction, RichBlock>::block_number(client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::get_code(client, address, None).await.unwrap();
EthApiClient::<Transaction, RichBlock>::send_raw_transaction(client, tx).await.unwrap();
EthApiClient::<Transaction, RichBlock>::fee_history(client, U64::from(0), block_number, None)
.await
.unwrap();
EthApiClient::call(client, call_request.clone(), Some(block_number.into()), None, None)
EthApiClient::<Transaction, RichBlock>::balance(client, address, None).await.unwrap();
EthApiClient::<Transaction, RichBlock>::transaction_count(client, address, None).await.unwrap();
EthApiClient::<Transaction, RichBlock>::storage_at(
client,
address,
U256::default().into(),
None,
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::block_by_hash(client, hash, false).await.unwrap();
EthApiClient::<Transaction, RichBlock>::block_by_number(client, block_number, false)
.await
.unwrap();
EthApiClient::syncing(client).await.unwrap();
EthApiClient::send_transaction(client, transaction_request).await.unwrap_err();
EthApiClient::hashrate(client).await.unwrap();
EthApiClient::submit_hashrate(client, U256::default(), B256::default()).await.unwrap();
EthApiClient::gas_price(client).await.unwrap_err();
EthApiClient::max_priority_fee_per_gas(client).await.unwrap_err();
EthApiClient::get_proof(client, address, vec![], None).await.unwrap();
EthApiClient::<Transaction, RichBlock>::block_transaction_count_by_number(client, block_number)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::block_transaction_count_by_hash(client, hash)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::block_uncles_count_by_hash(client, hash).await.unwrap();
EthApiClient::<Transaction, RichBlock>::block_uncles_count_by_number(client, block_number)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::uncle_by_block_hash_and_index(client, hash, index)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::uncle_by_block_number_and_index(
client,
block_number,
index,
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::sign(client, address, bytes.clone()).await.unwrap_err();
EthApiClient::<Transaction, RichBlock>::sign_typed_data(client, address, typed_data)
.await
.unwrap_err();
EthApiClient::<Transaction, RichBlock>::transaction_by_hash(client, tx_hash).await.unwrap();
EthApiClient::<Transaction, RichBlock>::transaction_by_block_hash_and_index(
client, hash, index,
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::transaction_by_block_number_and_index(
client,
block_number,
index,
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::create_access_list(
client,
call_request.clone(),
Some(block_number.into()),
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::estimate_gas(
client,
call_request.clone(),
Some(block_number.into()),
None,
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::call(
client,
call_request.clone(),
Some(block_number.into()),
None,
None,
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::syncing(client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::send_transaction(client, transaction_request)
.await
.unwrap_err();
EthApiClient::<Transaction, RichBlock>::hashrate(client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::submit_hashrate(
client,
U256::default(),
B256::default(),
)
.await
.unwrap();
EthApiClient::<Transaction, RichBlock>::gas_price(client).await.unwrap_err();
EthApiClient::<Transaction, RichBlock>::max_priority_fee_per_gas(client).await.unwrap_err();
EthApiClient::<Transaction, RichBlock>::get_proof(client, address, vec![], None).await.unwrap();
// Unimplemented
assert!(is_unimplemented(EthApiClient::author(client).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::is_mining(client).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::get_work(client).await.err().unwrap()));
assert!(is_unimplemented(
EthApiClient::submit_work(client, B64::default(), B256::default(), B256::default())
EthApiClient::<Transaction, RichBlock>::author(client).await.err().unwrap()
));
assert!(is_unimplemented(
EthApiClient::<Transaction, RichBlock>::is_mining(client).await.err().unwrap()
));
assert!(is_unimplemented(
EthApiClient::<Transaction, RichBlock>::get_work(client).await.err().unwrap()
));
assert!(is_unimplemented(
EthApiClient::<Transaction, RichBlock>::submit_work(
client,
B64::default(),
B256::default(),
B256::default()
)
.await
.err()
.unwrap()
));
assert!(is_unimplemented(
EthApiClient::<Transaction, RichBlock>::sign_transaction(client, call_request.clone())
.await
.err()
.unwrap()
));
assert!(is_unimplemented(
EthApiClient::sign_transaction(client, call_request.clone()).await.err().unwrap()
));
}
async fn test_basic_debug_calls<C>(client: &C)

View File

@ -8,6 +8,7 @@ use reth_rpc::EthApi;
use reth_rpc_builder::{RpcServerConfig, TransportRpcModuleConfig};
use reth_rpc_eth_api::EthApiClient;
use reth_rpc_server_types::RpcModuleSelection;
use reth_rpc_types::{RichBlock, Transaction};
use std::{
future::Future,
pin::Pin,
@ -74,7 +75,7 @@ async fn test_rpc_middleware() {
.unwrap();
let client = handle.http_client().unwrap();
EthApiClient::protocol_version(&client).await.unwrap();
EthApiClient::<Transaction, RichBlock>::protocol_version(&client).await.unwrap();
let count = mylayer.count.load(Ordering::Relaxed);
assert_eq!(count, 1);
}

View File

@ -33,6 +33,8 @@ reth-network-api.workspace = true
# ethereum
alloy-dyn-abi = { workspace = true, features = ["eip712"] }
alloy-network.workspace = true
alloy-json-rpc.workspace = true
# rpc
jsonrpsee = { workspace = true, features = ["server", "macros"] }

View File

@ -1,11 +1,8 @@
//! Implementation of the [`jsonrpsee`] generated [`EthApiServer`] trait. Handles RPC requests for
//! the `eth_` namespace.
use crate::helpers::{
transaction::UpdateRawTxForwarder, EthApiSpec, EthBlocks, EthCall, EthFees, EthState,
EthTransactions, FullEthApi,
};
use alloy_dyn_abi::TypedData;
use alloy_json_rpc::RpcObject;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_primitives::{
transaction::AccessListResult, Address, BlockId, BlockNumberOrTag, Bytes, B256, B64, U256, U64,
@ -15,22 +12,41 @@ use reth_rpc_types::{
serde_helpers::JsonStorageKey,
simulate::{SimBlock, SimulatedBlock},
state::{EvmOverrides, StateOverride},
AnyTransactionReceipt, Block, BlockOverrides, Bundle, EIP1186AccountProofResponse,
EthCallResponse, FeeHistory, Header, Index, RichBlock, StateContext, SyncStatus, Transaction,
TransactionRequest, Work,
AnyTransactionReceipt, BlockOverrides, Bundle, EIP1186AccountProofResponse, EthCallResponse,
FeeHistory, Header, Index, StateContext, SyncStatus, TransactionRequest, Work,
};
use tracing::trace;
use crate::{
helpers::{
transaction::UpdateRawTxForwarder, EthApiSpec, EthBlocks, EthCall, EthFees, EthState,
EthTransactions, FullEthApi,
},
RpcBlock, RpcTransaction,
};
/// Helper trait, unifies functionality that must be supported to implement all RPC methods for
/// server.
pub trait FullEthApiServer: EthApiServer + FullEthApi + UpdateRawTxForwarder + Clone {}
pub trait FullEthApiServer:
EthApiServer<RpcTransaction<Self::NetworkTypes>, RpcBlock<Self::NetworkTypes>>
+ FullEthApi
+ UpdateRawTxForwarder
+ Clone
{
}
impl<T> FullEthApiServer for T where T: EthApiServer + FullEthApi + UpdateRawTxForwarder + Clone {}
impl<T> FullEthApiServer for T where
T: EthApiServer<RpcTransaction<T::NetworkTypes>, RpcBlock<T::NetworkTypes>>
+ FullEthApi
+ UpdateRawTxForwarder
+ Clone
{
}
/// Eth rpc interface: <https://ethereum.github.io/execution-apis/api-documentation/>
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))]
pub trait EthApi {
pub trait EthApi<T: RpcObject, B: RpcObject> {
/// Returns the protocol version encoded as a string.
#[method(name = "protocolVersion")]
async fn protocol_version(&self) -> RpcResult<U64>;
@ -57,15 +73,11 @@ pub trait EthApi {
/// Returns information about a block by hash.
#[method(name = "getBlockByHash")]
async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult<Option<RichBlock>>;
async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult<Option<B>>;
/// Returns information about a block by number.
#[method(name = "getBlockByNumber")]
async fn block_by_number(
&self,
number: BlockNumberOrTag,
full: bool,
) -> RpcResult<Option<RichBlock>>;
async fn block_by_number(&self, number: BlockNumberOrTag, full: bool) -> RpcResult<Option<B>>;
/// Returns the number of transactions in a block from a block matching the given block hash.
#[method(name = "getBlockTransactionCountByHash")]
@ -98,11 +110,8 @@ pub trait EthApi {
/// Returns an uncle block of the given block and index.
#[method(name = "getUncleByBlockHashAndIndex")]
async fn uncle_by_block_hash_and_index(
&self,
hash: B256,
index: Index,
) -> RpcResult<Option<Block>>;
async fn uncle_by_block_hash_and_index(&self, hash: B256, index: Index)
-> RpcResult<Option<B>>;
/// Returns an uncle block of the given block and index.
#[method(name = "getUncleByBlockNumberAndIndex")]
@ -110,7 +119,7 @@ pub trait EthApi {
&self,
number: BlockNumberOrTag,
index: Index,
) -> RpcResult<Option<Block>>;
) -> RpcResult<Option<B>>;
/// Returns the EIP-2718 encoded transaction if it exists.
///
@ -120,7 +129,7 @@ pub trait EthApi {
/// Returns the information about a transaction requested by transaction hash.
#[method(name = "getTransactionByHash")]
async fn transaction_by_hash(&self, hash: B256) -> RpcResult<Option<Transaction>>;
async fn transaction_by_hash(&self, hash: B256) -> RpcResult<Option<T>>;
/// Returns information about a raw transaction by block hash and transaction index position.
#[method(name = "getRawTransactionByBlockHashAndIndex")]
@ -136,7 +145,7 @@ pub trait EthApi {
&self,
hash: B256,
index: Index,
) -> RpcResult<Option<Transaction>>;
) -> RpcResult<Option<T>>;
/// Returns information about a raw transaction by block number and transaction index
/// position.
@ -153,7 +162,7 @@ pub trait EthApi {
&self,
number: BlockNumberOrTag,
index: Index,
) -> RpcResult<Option<Transaction>>;
) -> RpcResult<Option<T>>;
/// Returns the receipt of a transaction by transaction hash.
#[method(name = "getTransactionReceipt")]
@ -347,7 +356,7 @@ pub trait EthApi {
}
#[async_trait::async_trait]
impl<T> EthApiServer for T
impl<T> EthApiServer<RpcTransaction<T::NetworkTypes>, RpcBlock<T::NetworkTypes>> for T
where
T: FullEthApi,
jsonrpsee_types::error::ErrorObject<'static>: From<T::Error>,
@ -390,7 +399,11 @@ where
}
/// Handler for: `eth_getBlockByHash`
async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult<Option<RichBlock>> {
async fn block_by_hash(
&self,
hash: B256,
full: bool,
) -> RpcResult<Option<RpcBlock<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?hash, ?full, "Serving eth_getBlockByHash");
Ok(EthBlocks::rpc_block(self, hash.into(), full).await?)
}
@ -400,7 +413,7 @@ where
&self,
number: BlockNumberOrTag,
full: bool,
) -> RpcResult<Option<RichBlock>> {
) -> RpcResult<Option<RpcBlock<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?number, ?full, "Serving eth_getBlockByNumber");
Ok(EthBlocks::rpc_block(self, number.into(), full).await?)
}
@ -449,7 +462,7 @@ where
&self,
hash: B256,
index: Index,
) -> RpcResult<Option<Block>> {
) -> RpcResult<Option<RpcBlock<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?hash, ?index, "Serving eth_getUncleByBlockHashAndIndex");
Ok(EthBlocks::ommer_by_block_and_index(self, hash.into(), index).await?)
}
@ -459,7 +472,7 @@ where
&self,
number: BlockNumberOrTag,
index: Index,
) -> RpcResult<Option<Block>> {
) -> RpcResult<Option<RpcBlock<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?number, ?index, "Serving eth_getUncleByBlockNumberAndIndex");
Ok(EthBlocks::ommer_by_block_and_index(self, number.into(), index).await?)
}
@ -471,7 +484,10 @@ where
}
/// Handler for: `eth_getTransactionByHash`
async fn transaction_by_hash(&self, hash: B256) -> RpcResult<Option<Transaction>> {
async fn transaction_by_hash(
&self,
hash: B256,
) -> RpcResult<Option<RpcTransaction<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?hash, "Serving eth_getTransactionByHash");
Ok(EthTransactions::transaction_by_hash(self, hash).await?.map(Into::into))
}
@ -492,7 +508,7 @@ where
&self,
hash: B256,
index: Index,
) -> RpcResult<Option<reth_rpc_types::Transaction>> {
) -> RpcResult<Option<RpcTransaction<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?hash, ?index, "Serving eth_getTransactionByBlockHashAndIndex");
Ok(EthTransactions::transaction_by_block_and_tx_index(self, hash.into(), index.into())
.await?)
@ -518,7 +534,7 @@ where
&self,
number: BlockNumberOrTag,
index: Index,
) -> RpcResult<Option<reth_rpc_types::Transaction>> {
) -> RpcResult<Option<RpcTransaction<T::NetworkTypes>>> {
trace!(target: "rpc::eth", ?number, ?index, "Serving eth_getTransactionByBlockNumberAndIndex");
Ok(EthTransactions::transaction_by_block_and_tx_index(self, number.into(), index.into())
.await?)

View File

@ -1,12 +1,13 @@
//! `eth_` RPC API for filtering.
use alloy_json_rpc::RpcObject;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_rpc_types::{Filter, FilterChanges, FilterId, Log, PendingTransactionFilterKind};
/// Rpc Interface for poll-based ethereum filter API.
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))]
pub trait EthFilterApi {
pub trait EthFilterApi<T: RpcObject> {
/// Creates anew filter and returns its id.
#[method(name = "newFilter")]
async fn new_filter(&self, filter: Filter) -> RpcResult<FilterId>;
@ -24,7 +25,7 @@ pub trait EthFilterApi {
/// Returns all filter changes since last poll.
#[method(name = "getFilterChanges")]
async fn filter_changes(&self, id: FilterId) -> RpcResult<FilterChanges>;
async fn filter_changes(&self, id: FilterId) -> RpcResult<FilterChanges<T>>;
/// Returns all logs matching given filter (in a range 'from' - 'to').
#[method(name = "getFilterLogs")]

View File

@ -6,10 +6,10 @@ use futures::Future;
use reth_primitives::{BlockId, Receipt, SealedBlock, SealedBlockWithSenders, TransactionMeta};
use reth_provider::{BlockIdReader, BlockReader, BlockReaderIdExt, HeaderProvider};
use reth_rpc_eth_types::{EthApiError, EthStateCache, ReceiptBuilder};
use reth_rpc_types::{AnyTransactionReceipt, Block, Header, Index, RichBlock};
use reth_rpc_types::{AnyTransactionReceipt, Header, Index};
use reth_rpc_types_compat::block::{from_block, uncle_block_from_header};
use crate::FromEthApiError;
use crate::{FromEthApiError, RpcBlock};
use super::{LoadPendingBlock, LoadReceipt, SpawnBlocking};
@ -25,11 +25,8 @@ pub trait EthBlocks: LoadBlock {
fn rpc_block_header(
&self,
block_id: BlockId,
) -> impl Future<Output = Result<Option<Header>, Self::Error>> + Send
where
Self: LoadPendingBlock + SpawnBlocking,
{
async move { Ok(self.rpc_block(block_id, false).await?.map(|block| block.inner.header)) }
) -> impl Future<Output = Result<Option<Header>, Self::Error>> + Send {
async move { Ok(self.rpc_block(block_id, false).await?.map(|block| block.header)) }
}
/// Returns the populated rpc block object for the given block id.
@ -40,9 +37,7 @@ pub trait EthBlocks: LoadBlock {
&self,
block_id: BlockId,
full: bool,
) -> impl Future<Output = Result<Option<RichBlock>, Self::Error>> + Send
where
Self: LoadPendingBlock + SpawnBlocking,
) -> impl Future<Output = Result<Option<RpcBlock<Self::NetworkTypes>>, Self::Error>> + Send
{
async move {
let block = match self.block_with_senders(block_id).await? {
@ -56,7 +51,7 @@ pub trait EthBlocks: LoadBlock {
.ok_or(EthApiError::UnknownBlockNumber)?;
let block = from_block(block.unseal(), total_difficulty, full.into(), Some(block_hash))
.map_err(Self::Error::from_eth_err)?;
Ok(Some(block.into()))
Ok(Some(block))
}
}
@ -187,7 +182,8 @@ pub trait EthBlocks: LoadBlock {
&self,
block_id: BlockId,
index: Index,
) -> impl Future<Output = Result<Option<Block>, Self::Error>> + Send {
) -> impl Future<Output = Result<Option<RpcBlock<Self::NetworkTypes>>, Self::Error>> + Send
{
async move {
let uncles = if block_id.is_pending() {
// Pending block can be fetched directly without need for caching

View File

@ -26,7 +26,6 @@ pub mod spec;
pub mod state;
pub mod trace;
pub mod transaction;
pub mod types;
pub use block::{EthBlocks, LoadBlock};
pub use blocking_task::SpawnBlocking;

View File

@ -19,12 +19,12 @@ use reth_rpc_types::{
EIP1559TransactionRequest, EIP2930TransactionRequest, EIP4844TransactionRequest,
LegacyTransactionRequest,
},
AnyTransactionReceipt, Transaction, TransactionRequest, TypedTransactionRequest,
AnyTransactionReceipt, TransactionRequest, TypedTransactionRequest,
};
use reth_rpc_types_compat::transaction::from_recovered_with_block_context;
use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool};
use crate::{FromEthApiError, IntoEthApiError};
use crate::{FromEthApiError, IntoEthApiError, RpcTransaction};
use super::{
Call, EthApiSpec, EthSigner, LoadBlock, LoadFee, LoadPendingBlock, LoadReceipt, SpawnBlocking,
@ -188,14 +188,14 @@ pub trait EthTransactions: LoadTransaction {
})
}
/// Get [`Transaction`] by [`BlockId`] and index of transaction within that block.
/// Get transaction by [`BlockId`] and index of transaction within that block.
///
/// Returns `Ok(None)` if the block does not exist, or index is out of range.
fn transaction_by_block_and_tx_index(
&self,
block_id: BlockId,
index: usize,
) -> impl Future<Output = Result<Option<Transaction>, Self::Error>> + Send
) -> impl Future<Output = Result<Option<RpcTransaction<Self::NetworkTypes>>, Self::Error>> + Send
where
Self: LoadBlock,
{

View File

@ -1,17 +0,0 @@
//! Trait for specifying `eth` API types that may be network dependent.
use std::error::Error;
use crate::{AsEthApiError, FromEthApiError, FromEvmError};
/// Network specific `eth` API types.
pub trait EthApiTypes: Send + Sync {
/// Extension of [`EthApiError`](reth_rpc_eth_types::EthApiError), with network specific errors.
type Error: Into<jsonrpsee_types::error::ErrorObject<'static>>
+ FromEthApiError
+ AsEthApiError
+ FromEvmError
+ Error
+ Send
+ Sync;
}

View File

@ -17,17 +17,17 @@ pub mod core;
pub mod filter;
pub mod helpers;
pub mod pubsub;
pub mod types;
pub use bundle::{EthBundleApiServer, EthCallBundleApiServer};
pub use core::{EthApiServer, FullEthApiServer};
pub use filter::EthFilterApiServer;
pub use helpers::{
error::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError},
types::EthApiTypes,
transaction::RawTransactionForwarder,
};
pub use pubsub::EthPubSubApiServer;
pub use helpers::transaction::RawTransactionForwarder;
pub use types::{EthApiTypes, RpcBlock, RpcTransaction};
#[cfg(feature = "client")]
pub use bundle::{EthBundleApiClient, EthCallBundleApiClient};

View File

@ -1,11 +1,12 @@
//! `eth_` RPC API for pubsub subscription.
use alloy_json_rpc::RpcObject;
use jsonrpsee::proc_macros::rpc;
use reth_rpc_types::pubsub::{Params, SubscriptionKind};
/// Ethereum pub-sub rpc interface.
#[rpc(server, namespace = "eth")]
pub trait EthPubSubApi {
pub trait EthPubSubApi<T: RpcObject> {
/// Create an ethereum subscription for the given params
#[subscription(
name = "subscribe" => "subscription",

View File

@ -0,0 +1,35 @@
//! Trait for specifying `eth` network dependent API types.
use std::error::Error;
use alloy_network::{Ethereum, Network};
use reth_rpc_eth_types::EthApiError;
use reth_rpc_types::{Block, Transaction};
use crate::{AsEthApiError, FromEthApiError, FromEvmError};
/// Network specific `eth` API types.
pub trait EthApiTypes: Send + Sync + Clone {
/// Extension of [`EthApiError`], with network specific errors.
type Error: Into<jsonrpsee_types::error::ErrorObject<'static>>
+ FromEthApiError
+ AsEthApiError
+ FromEvmError
+ Error
+ Send
+ Sync;
/// Blockchain primitive types, specific to network, e.g. block and transaction.
// todo: remove restriction `reth_rpc_types::Transaction`
type NetworkTypes: Network<TransactionResponse = Transaction>;
}
impl EthApiTypes for () {
type Error = EthApiError;
type NetworkTypes = Ethereum;
}
/// Adapter for network specific transaction type.
pub type RpcTransaction<T> = <T as Network>::TransactionResponse;
/// Adapter for network specific block type.
pub type RpcBlock<T> = Block<RpcTransaction<T>>;

View File

@ -30,3 +30,4 @@ similar-asserts.workspace = true
[dev-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "rt"] }
reth-rpc-eth-api.workspace = true
jsonrpsee-http-client.workspace = true

View File

@ -1,5 +1,11 @@
//! Helpers for testing debug trace calls.
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use futures::{Stream, StreamExt};
use jsonrpsee::core::client::Error as RpcError;
use reth_primitives::{BlockId, TxHash, B256};
@ -9,12 +15,7 @@ use reth_rpc_types::{
common::TraceResult,
geth::{GethDebugTracerType, GethDebugTracingOptions, GethTrace},
},
TransactionRequest,
};
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
RichBlock, Transaction, TransactionRequest,
};
const NOOP_TRACER: &str = include_str!("../assets/noop-tracer.js");
@ -76,7 +77,7 @@ pub trait DebugApiExt {
impl<T> DebugApiExt for T
where
T: EthApiClient + DebugApiClient + Sync,
T: EthApiClient<Transaction, RichBlock> + DebugApiClient + Sync,
{
type Provider = T;

View File

@ -1,11 +1,14 @@
use std::{collections::HashSet, time::Instant};
use futures::StreamExt;
use jsonrpsee::http_client::HttpClientBuilder;
use jsonrpsee_http_client::HttpClient;
use reth_rpc_api_testing_util::{debug::DebugApiExt, trace::TraceApiExt, utils::parse_env_url};
use reth_rpc_eth_api::EthApiClient;
use reth_rpc_types::trace::{
filter::TraceFilter, parity::TraceType, tracerequest::TraceCallRequest,
use reth_rpc_types::{
trace::{filter::TraceFilter, parity::TraceType, tracerequest::TraceCallRequest},
RichBlock, Transaction,
};
use std::{collections::HashSet, time::Instant};
/// This is intended to be run locally against a running node.
///
@ -106,7 +109,12 @@ async fn debug_trace_block_entire_chain() {
let url = url.unwrap();
let client = HttpClientBuilder::default().build(url).unwrap();
let current_block: u64 = client.block_number().await.unwrap().try_into().unwrap();
let current_block: u64 =
<HttpClient as EthApiClient<Transaction, RichBlock>>::block_number(&client)
.await
.unwrap()
.try_into()
.unwrap();
let range = 0..=current_block;
let mut stream = client.debug_trace_block_buffered_unordered(range, None, 20);
let now = Instant::now();

View File

@ -41,6 +41,7 @@ alloy-dyn-abi.workspace = true
alloy-rlp.workspace = true
alloy-primitives.workspace = true
alloy-genesis.workspace = true
alloy-network.workspace = true
revm = { workspace = true, features = [
"optional_block_gas_limit",
"optional_eip3607",

View File

@ -1,11 +1,13 @@
use alloy_network::Network;
use jsonrpsee::core::RpcResult as Result;
use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, B256, U256, U64};
use reth_rpc_api::{EngineEthApiServer, EthApiServer, EthFilterApiServer};
/// Re-export for convenience
pub use reth_rpc_engine_api::EngineApi;
use reth_rpc_eth_api::{EthApiTypes, RpcBlock, RpcTransaction};
use reth_rpc_types::{
state::StateOverride, BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log,
RichBlock, SyncStatus, TransactionRequest,
SyncStatus, TransactionRequest,
};
use tracing_futures::Instrument;
@ -31,10 +33,15 @@ impl<Eth, EthFilter> EngineEthApi<Eth, EthFilter> {
}
#[async_trait::async_trait]
impl<Eth, EthFilter> EngineEthApiServer for EngineEthApi<Eth, EthFilter>
impl<Eth, EthFilter>
EngineEthApiServer<
reth_rpc_types::Transaction,
reth_rpc_types::Block<reth_rpc_types::Transaction>,
> for EngineEthApi<Eth, EthFilter>
where
Eth: EthApiServer,
EthFilter: EthFilterApiServer,
Eth: EthApiServer<RpcTransaction<Eth::NetworkTypes>, RpcBlock<Eth::NetworkTypes>>
+ EthApiTypes<NetworkTypes: Network<TransactionResponse = reth_rpc_types::Transaction>>,
EthFilter: EthFilterApiServer<reth_rpc_types::Transaction>,
{
/// Handler for: `eth_syncing`
fn syncing(&self) -> Result<SyncStatus> {
@ -77,7 +84,11 @@ where
}
/// Handler for: `eth_getBlockByHash`
async fn block_by_hash(&self, hash: B256, full: bool) -> Result<Option<RichBlock>> {
async fn block_by_hash(
&self,
hash: B256,
full: bool,
) -> Result<Option<RpcBlock<Eth::NetworkTypes>>> {
self.eth.block_by_hash(hash, full).instrument(engine_span!()).await
}
@ -86,7 +97,7 @@ where
&self,
number: BlockNumberOrTag,
full: bool,
) -> Result<Option<RichBlock>> {
) -> Result<Option<RpcBlock<Eth::NetworkTypes>>> {
self.eth.block_by_number(number, full).instrument(engine_span!()).await
}

View File

@ -3,6 +3,7 @@
use std::sync::Arc;
use alloy_network::Ethereum;
use derive_more::Deref;
use reth_node_api::{BuilderProvider, FullNodeComponents};
use reth_primitives::{BlockNumberOrTag, U256};
@ -36,6 +37,12 @@ pub struct EthApi<Provider, Pool, Network, EvmConfig> {
pub(super) inner: Arc<EthApiInner<Provider, Pool, Network, EvmConfig>>,
}
impl<Provider, Pool, Network, EvmConfig> Clone for EthApi<Provider, Pool, Network, EvmConfig> {
fn clone(&self) -> Self {
Self { inner: self.inner.clone() }
}
}
impl<Provider, Pool, Network, EvmConfig> EthApi<Provider, Pool, Network, EvmConfig>
where
Provider: BlockReaderIdExt,
@ -119,6 +126,7 @@ where
Self: Send + Sync,
{
type Error = EthApiError;
type NetworkTypes = Ethereum;
}
impl<Provider, Pool, Network, EvmConfig> std::fmt::Debug
@ -129,12 +137,6 @@ impl<Provider, Pool, Network, EvmConfig> std::fmt::Debug
}
}
impl<Provider, Pool, Network, EvmConfig> Clone for EthApi<Provider, Pool, Network, EvmConfig> {
fn clone(&self) -> Self {
Self { inner: Arc::clone(&self.inner) }
}
}
impl<Provider, Pool, Network, EvmConfig> SpawnBlocking
for EthApi<Provider, Pool, Network, EvmConfig>
where
@ -509,7 +511,7 @@ mod tests {
/// Invalid block range
#[tokio::test]
async fn test_fee_history_empty() {
let response = <EthApi<_, _, _, _> as EthApiServer>::fee_history(
let response = <EthApi<_, _, _, _> as EthApiServer<_, _>>::fee_history(
&build_test_eth_api(NoopProvider::default()),
U64::from(1),
BlockNumberOrTag::Latest,
@ -531,7 +533,7 @@ mod tests {
let (eth_api, _, _) =
prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default());
let response = <EthApi<_, _, _, _> as EthApiServer>::fee_history(
let response = <EthApi<_, _, _, _> as EthApiServer<_, _>>::fee_history(
&eth_api,
U64::from(newest_block + 1),
newest_block.into(),
@ -554,7 +556,7 @@ mod tests {
let (eth_api, _, _) =
prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default());
let response = <EthApi<_, _, _, _> as EthApiServer>::fee_history(
let response = <EthApi<_, _, _, _> as EthApiServer<_, _>>::fee_history(
&eth_api,
U64::from(1),
(newest_block + 1000).into(),
@ -577,7 +579,7 @@ mod tests {
let (eth_api, _, _) =
prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default());
let response = <EthApi<_, _, _, _> as EthApiServer>::fee_history(
let response = <EthApi<_, _, _, _> as EthApiServer<_, _>>::fee_history(
&eth_api,
U64::from(0),
newest_block.into(),

View File

@ -219,7 +219,7 @@ where
}
#[async_trait]
impl<Provider, Pool> EthFilterApiServer for EthFilter<Provider, Pool>
impl<Provider, Pool> EthFilterApiServer<reth_rpc_types::Transaction> for EthFilter<Provider, Pool>
where
Provider: BlockReader + BlockIdReader + EvmEnvProvider + 'static,
Pool: TransactionPool + 'static,

View File

@ -12,7 +12,7 @@ where
Provider: HeaderProvider,
{
#[inline]
fn provider(&self) -> impl reth_provider::HeaderProvider {
fn provider(&self) -> impl HeaderProvider {
self.inner.provider()
}
}

View File

@ -68,7 +68,7 @@ impl<Provider, Pool, Events, Network> EthPubSub<Provider, Pool, Events, Network>
}
#[async_trait::async_trait]
impl<Provider, Pool, Events, Network> EthPubSubApiServer
impl<Provider, Pool, Events, Network> EthPubSubApiServer<reth_rpc_types::Transaction>
for EthPubSub<Provider, Pool, Events, Network>
where
Provider: BlockReader + EvmEnvProvider + Clone + 'static,

View File

@ -1,9 +1,10 @@
use alloy_network::Network;
use alloy_primitives::Bytes;
use async_trait::async_trait;
use jsonrpsee::core::RpcResult;
use reth_primitives::{Address, BlockNumberOrTag, TxHash, B256, U256};
use reth_rpc_api::{EthApiServer, OtterscanServer};
use reth_rpc_eth_api::helpers::TraceExt;
use reth_rpc_eth_api::{helpers::TraceExt, EthApiTypes, RpcBlock, RpcTransaction};
use reth_rpc_eth_types::EthApiError;
use reth_rpc_server_types::result::internal_rpc_err;
use reth_rpc_types::{
@ -14,7 +15,7 @@ use reth_rpc_types::{
},
parity::{Action, CreateAction, CreateOutput, TraceOutput},
},
AnyTransactionReceipt, BlockTransactions, Header, RichBlock,
AnyTransactionReceipt, BlockTransactions, Header, Rich,
};
use revm_inspectors::{
tracing::{types::CallTraceNode, TracingInspectorConfig},
@ -36,11 +37,16 @@ impl<Eth> OtterscanApi<Eth> {
pub const fn new(eth: Eth) -> Self {
Self { eth }
}
}
impl<Eth> OtterscanApi<Eth>
where
Eth: EthApiTypes<NetworkTypes: Network<TransactionResponse = reth_rpc_types::Transaction>>,
{
/// Constructs a `BlockDetails` from a block and its receipts.
fn block_details(
&self,
block: Option<RichBlock>,
block: Option<RpcBlock<Eth::NetworkTypes>>,
receipts: Option<Vec<AnyTransactionReceipt>>,
) -> RpcResult<BlockDetails> {
let block = block.ok_or_else(|| EthApiError::UnknownBlockNumber)?;
@ -52,14 +58,21 @@ impl<Eth> OtterscanApi<Eth> {
.map(|receipt| receipt.gas_used.saturating_mul(receipt.effective_gas_price))
.sum::<u128>();
Ok(BlockDetails::new(block, Default::default(), U256::from(total_fees)))
Ok(BlockDetails::new(
Rich { inner: block, extra_info: Default::default() },
Default::default(),
U256::from(total_fees),
))
}
}
#[async_trait]
impl<Eth> OtterscanServer for OtterscanApi<Eth>
where
Eth: EthApiServer + TraceExt + 'static,
Eth: EthApiServer<RpcTransaction<Eth::NetworkTypes>, RpcBlock<Eth::NetworkTypes>>
+ EthApiTypes<NetworkTypes: Network<TransactionResponse = reth_rpc_types::Transaction>>
+ TraceExt
+ 'static,
{
/// Handler for `{ots,erigon}_getHeaderByNumber`
async fn get_header_by_number(&self, block_number: u64) -> RpcResult<Option<Header>> {
@ -193,7 +206,7 @@ where
}
// make sure the block is full
let BlockTransactions::Full(transactions) = &mut block.inner.transactions else {
let BlockTransactions::Full(transactions) = &mut block.transactions else {
return Err(internal_rpc_err("block is not full"));
};
@ -235,7 +248,7 @@ where
.collect();
// use `transaction_count` to indicate the paginate information
let mut block = OtsBlockTransactions { fullblock: block.inner.into(), receipts };
let mut block = OtsBlockTransactions { fullblock: block.into(), receipts };
block.fullblock.transaction_count = tx_len;
Ok(block)
}
@ -299,14 +312,14 @@ where
.await?;
let Some(BlockTransactions::Full(transactions)) =
self.eth.block_by_number(num.into(), true).await?.map(|block| block.inner.transactions)
self.eth.block_by_number(num.into(), true).await?.map(|block| block.transactions)
else {
return Err(EthApiError::UnknownBlockNumber.into());
};
Ok(transactions
.into_iter()
.find(|tx| tx.from == sender && tx.nonce == nonce)
.find(|tx| *tx.from == *sender && tx.nonce == nonce)
.map(|tx| tx.hash))
}

View File

@ -144,7 +144,7 @@ pub struct MyExecutorBuilder;
impl<Node> ExecutorBuilder<Node> for MyExecutorBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type EVM = MyEvmConfig;
type Executor = EthExecutorProvider<Self::EVM>;

View File

@ -11,7 +11,5 @@ reth.workspace = true
reth-node-ethereum.workspace = true
reth-transaction-pool.workspace = true
reth-tracing.workspace = true
reth-chainspec.workspace = true
eyre.workspace = true

View File

@ -10,7 +10,6 @@ use reth::{
blobstore::InMemoryBlobStore, EthTransactionPool, TransactionValidationTaskExecutor,
},
};
use reth_chainspec::ChainSpec;
use reth_node_ethereum::{node::EthereumAddOns, EthereumNode};
use reth_tracing::tracing::{debug, info};
use reth_transaction_pool::PoolConfig;
@ -46,7 +45,7 @@ pub struct CustomPoolBuilder {
/// This will be used to build the transaction pool and its maintenance tasks during launch.
impl<Node> PoolBuilder<Node> for CustomPoolBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type Pool = EthTransactionPool<Node::Provider, InMemoryBlobStore>;

View File

@ -207,7 +207,7 @@ pub struct MyExecutorBuilder {
impl<Node> ExecutorBuilder<Node> for MyExecutorBuilder
where
Node: FullNodeTypes<ChainSpec = ChainSpec>,
Node: FullNodeTypes,
{
type EVM = MyEvmConfig;
type Executor = EthExecutorProvider<Self::EVM>;