feat: extract optimism sequencer client to node-optimism (#7482)

This commit is contained in:
Matthias Seitz
2024-04-05 23:35:02 +02:00
committed by GitHub
parent 71c404d9cb
commit b89af430e2
27 changed files with 221 additions and 163 deletions

9
Cargo.lock generated
View File

@ -6795,9 +6795,15 @@ dependencies = [
name = "reth-node-optimism"
version = "0.2.0-beta.5"
dependencies = [
"async-trait",
"clap",
"eyre",
"http",
"http-body",
"hyper",
"jsonrpsee",
"parking_lot 0.12.1",
"reqwest",
"reth-basic-payload-builder",
"reth-db",
"reth-network",
@ -6815,6 +6821,8 @@ dependencies = [
"reth-transaction-pool",
"revm",
"serde",
"serde_json",
"thiserror",
]
[[package]]
@ -7014,7 +7022,6 @@ dependencies = [
"parking_lot 0.12.1",
"pin-project",
"rand 0.8.5",
"reqwest",
"reth-consensus-common",
"reth-evm",
"reth-evm-ethereum",

View File

@ -125,8 +125,6 @@ optimism = [
"reth-provider/optimism",
"reth-beacon-consensus/optimism",
"reth-auto-seal-consensus/optimism",
"reth-network/optimism",
"reth-network-api/optimism",
"reth-blockchain-tree/optimism",
"dep:reth-node-optimism",
"reth-node-core/optimism"

View File

@ -3,8 +3,11 @@
use clap::Parser;
use reth::cli::Cli;
use reth_node_builder::NodeHandle;
use reth_node_optimism::{args::RollupArgs, OptimismEngineTypes, OptimismNode};
use reth_node_optimism::{
args::RollupArgs, rpc::SequencerClient, OptimismEngineTypes, OptimismNode,
};
use reth_provider::BlockReaderIdExt;
use std::sync::Arc;
// We use jemalloc for performance reasons
#[cfg(all(feature = "jemalloc", unix))]
@ -24,8 +27,20 @@ fn main() {
}
if let Err(err) = Cli::<RollupArgs>::parse().run(|builder, rollup_args| async move {
let NodeHandle { node, node_exit_future } =
builder.launch_node(OptimismNode::new(rollup_args.clone())).await?;
let NodeHandle { node, node_exit_future } = builder
.node(OptimismNode::new(rollup_args.clone()))
.extend_rpc_modules(move |ctx| {
// register sequencer tx forwarder
if let Some(sequencer_http) = rollup_args.sequencer_http.clone() {
ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(SequencerClient::new(
sequencer_http,
)));
}
Ok(())
})
.launch()
.await?;
// If `enable_genesis_walkback` is set to true, the rollup client will need to
// perform the derivation pipeline from genesis, validating the data dir.

View File

@ -27,5 +27,4 @@ tokio = { workspace = true, features = ["sync"] }
[features]
default = ["serde"]
serde = ["dep:serde"]
optimism = []
serde = ["dep:serde"]

View File

@ -46,10 +46,6 @@ pub trait NetworkInfo: Send + Sync {
/// Returns `true` when the node is undergoing the very first Pipeline sync.
fn is_initially_syncing(&self) -> bool;
/// Returns the sequencer HTTP endpoint, if set.
#[cfg(feature = "optimism")]
fn sequencer_endpoint(&self) -> Option<&str>;
}
/// Provides general purpose information about Peers in the network.

View File

@ -51,11 +51,6 @@ impl NetworkInfo for NoopNetwork {
fn is_initially_syncing(&self) -> bool {
false
}
#[cfg(feature = "optimism")]
fn sequencer_endpoint(&self) -> Option<&str> {
None
}
}
impl PeersInfo for NoopNetwork {

View File

@ -101,11 +101,6 @@ test-utils = [
"reth-transaction-pool/test-utils",
]
geth-tests = []
optimism = [
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-network-api/optimism",
]
[[bench]]
name = "bench"

View File

@ -80,17 +80,6 @@ pub struct NetworkConfig<C> {
pub tx_gossip_disabled: bool,
/// How to instantiate transactions manager.
pub transactions_manager_config: TransactionsManagerConfig,
/// Optimism Network Config
#[cfg(feature = "optimism")]
pub optimism_network_config: OptimismNetworkConfig,
}
/// Optimism Network Config
#[cfg(feature = "optimism")]
#[derive(Debug, Clone, Default)]
pub struct OptimismNetworkConfig {
/// The sequencer HTTP endpoint, if provided via CLI flag
pub sequencer_endpoint: Option<String>,
}
// === impl NetworkConfig ===
@ -227,18 +216,6 @@ pub struct NetworkConfigBuilder {
block_import: Option<Box<dyn BlockImport>>,
/// How to instantiate transactions manager.
transactions_manager_config: TransactionsManagerConfig,
/// Optimism Network Config Builder
#[cfg(feature = "optimism")]
optimism_network_config: OptimismNetworkConfigBuilder,
}
/// Optimism Network Config Builder
#[cfg(feature = "optimism")]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Default)]
pub struct OptimismNetworkConfigBuilder {
/// The sequencer HTTP endpoint, if provided via CLI flag
sequencer_endpoint: Option<String>,
}
// === impl NetworkConfigBuilder ===
@ -264,8 +241,6 @@ impl NetworkConfigBuilder {
head: None,
tx_gossip_disabled: false,
block_import: None,
#[cfg(feature = "optimism")]
optimism_network_config: OptimismNetworkConfigBuilder::default(),
transactions_manager_config: Default::default(),
}
}
@ -481,13 +456,6 @@ impl NetworkConfigBuilder {
self
}
/// Sets the sequencer HTTP endpoint.
#[cfg(feature = "optimism")]
pub fn sequencer_endpoint(mut self, endpoint: Option<String>) -> Self {
self.optimism_network_config.sequencer_endpoint = endpoint;
self
}
/// Convenience function for creating a [NetworkConfig] with a noop provider that does nothing.
#[cfg(any(test, feature = "test-utils"))]
pub fn build_with_noop_provider(
@ -522,8 +490,6 @@ impl NetworkConfigBuilder {
head,
tx_gossip_disabled,
block_import,
#[cfg(feature = "optimism")]
optimism_network_config: OptimismNetworkConfigBuilder { sequencer_endpoint },
transactions_manager_config,
} = self;
@ -578,8 +544,6 @@ impl NetworkConfigBuilder {
extra_protocols,
fork_filter,
tx_gossip_disabled,
#[cfg(feature = "optimism")]
optimism_network_config: OptimismNetworkConfig { sequencer_endpoint },
transactions_manager_config,
}
}

View File

@ -194,8 +194,6 @@ where
dns_discovery_config,
extra_protocols,
tx_gossip_disabled,
#[cfg(feature = "optimism")]
optimism_network_config: crate::config::OptimismNetworkConfig { sequencer_endpoint },
transactions_manager_config: _,
} = config;
@ -258,8 +256,6 @@ where
bandwidth_meter,
Arc::new(AtomicU64::new(chain_spec.chain.id())),
tx_gossip_disabled,
#[cfg(feature = "optimism")]
sequencer_endpoint,
discv4,
);

View File

@ -50,7 +50,6 @@ impl NetworkHandle {
bandwidth_meter: BandwidthMeter,
chain_id: Arc<AtomicU64>,
tx_gossip_disabled: bool,
#[cfg(feature = "optimism")] sequencer_endpoint: Option<String>,
discv4: Option<Discv4>,
) -> Self {
let inner = NetworkInner {
@ -66,8 +65,6 @@ impl NetworkHandle {
initial_sync_done: Arc::new(AtomicBool::new(false)),
chain_id,
tx_gossip_disabled,
#[cfg(feature = "optimism")]
sequencer_endpoint,
discv4,
};
Self { inner: Arc::new(inner) }
@ -329,11 +326,6 @@ impl NetworkInfo for NetworkHandle {
fn is_initially_syncing(&self) -> bool {
SyncStateProvider::is_initially_syncing(self)
}
#[cfg(feature = "optimism")]
fn sequencer_endpoint(&self) -> Option<&str> {
self.inner.sequencer_endpoint.as_deref()
}
}
impl SyncStateProvider for NetworkHandle {
@ -391,9 +383,6 @@ struct NetworkInner {
chain_id: Arc<AtomicU64>,
/// Whether to disable transaction gossip
tx_gossip_disabled: bool,
/// The sequencer HTTP Endpoint
#[cfg(feature = "optimism")]
sequencer_endpoint: Option<String>,
/// The instance of the discv4 service
discv4: Option<Discv4>,
}

View File

@ -103,8 +103,6 @@ optimism = [
"reth-rpc/optimism",
"reth-rpc-engine-api/optimism",
"reth-provider/optimism",
"reth-network/optimism",
"reth-network-api/optimism",
"reth-rpc-types-compat/optimism",
"reth-auto-seal-consensus/optimism",
"reth-consensus-common/optimism",

View File

@ -28,18 +28,29 @@ reth-network.workspace = true
reth-revm.workspace = true
revm.workspace = true
# async
async-trait.workspace = true
hyper.workspace = true
http = "0.2.8"
http-body = "0.4.5"
reqwest = { version = "0.11", default-features = false, features = [
"rustls-tls",
]}
# misc
clap.workspace = true
serde.workspace = true
serde_json.workspace = true
eyre.workspace = true
parking_lot.workspace = true
thiserror.workspace = true
jsonrpsee.workspace = true
[dev-dependencies]
reth-db.workspace = true
[features]
optimism = [
"reth-network/optimism",
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-rpc-types-compat/optimism",

View File

@ -27,6 +27,8 @@ pub use node::OptimismNode;
pub mod txpool;
pub mod rpc;
pub use reth_optimism_payload_builder::{
OptimismBuiltPayload, OptimismPayloadBuilder, OptimismPayloadBuilderAttributes,
};

View File

@ -41,12 +41,12 @@ impl OptimismNode {
where
Node: FullNodeTypes<Engine = OptimismEngineTypes>,
{
let RollupArgs { sequencer_http, disable_txpool_gossip, compute_pending_block, .. } = args;
let RollupArgs { disable_txpool_gossip, compute_pending_block, .. } = args;
ComponentsBuilder::default()
.node_types::<Node>()
.pool(OptimismPoolBuilder::default())
.payload(OptimismPayloadBuilder::new(compute_pending_block))
.network(OptimismNetworkBuilder { sequencer_http, disable_txpool_gossip })
.network(OptimismNetworkBuilder { disable_txpool_gossip })
}
}
@ -215,8 +215,6 @@ where
/// A basic optimism network builder.
#[derive(Debug, Default, Clone)]
pub struct OptimismNetworkBuilder {
/// HTTP endpoint for the sequencer mempool
pub sequencer_http: Option<String>,
/// Disable transaction pool gossip
pub disable_txpool_gossip: bool,
}
@ -231,14 +229,13 @@ where
ctx: &BuilderContext<Node>,
pool: Pool,
) -> eyre::Result<NetworkHandle> {
let Self { sequencer_http, disable_txpool_gossip } = self;
let Self { disable_txpool_gossip } = self;
let mut network_config = ctx.network_config()?;
// When `sequencer_endpoint` is configured, the node will forward all transactions to a
// Sequencer node for execution and inclusion on L1, and disable its own txpool
// gossip to prevent other parties in the network from learning about them.
network_config.tx_gossip_disabled = disable_txpool_gossip;
network_config.optimism_network_config.sequencer_endpoint = sequencer_http;
let network = NetworkManager::builder(network_config).await?;

View File

@ -0,0 +1,124 @@
//! Helpers for optimism specific RPC implementations.
use jsonrpsee::types::ErrorObject;
use reqwest::Client;
use reth_rpc::eth::{
error::{EthApiError, EthResult, ToRpcError},
traits::RawTransactionForwarder,
};
use reth_tracing::tracing;
use std::sync::{atomic::AtomicUsize, Arc};
/// Error type when interacting with the Sequencer
#[derive(Debug, thiserror::Error)]
pub enum SequencerRpcError {
/// Wrapper around a [hyper::Error].
#[error(transparent)]
HyperError(#[from] hyper::Error),
/// Wrapper around an [reqwest::Error].
#[error(transparent)]
HttpError(#[from] reqwest::Error),
/// Thrown when serializing transaction to forward to sequencer
#[error("invalid sequencer transaction")]
InvalidSequencerTransaction,
}
impl ToRpcError for SequencerRpcError {
fn to_rpc_error(&self) -> ErrorObject<'static> {
ErrorObject::owned(
jsonrpsee::types::error::INTERNAL_ERROR_CODE,
self.to_string(),
None::<String>,
)
}
}
impl From<SequencerRpcError> for EthApiError {
fn from(err: SequencerRpcError) -> Self {
EthApiError::other(err)
}
}
/// A client to interact with a Sequencer
#[derive(Debug, Clone)]
pub struct SequencerClient {
inner: Arc<SequencerClientInner>,
}
impl SequencerClient {
/// Creates a new [SequencerClient].
pub fn new(sequencer_endpoint: impl Into<String>) -> Self {
let client = Client::builder().use_rustls_tls().build().unwrap();
Self::with_client(sequencer_endpoint, client)
}
/// Creates a new [SequencerClient].
pub fn with_client(sequencer_endpoint: impl Into<String>, http_client: Client) -> Self {
let inner = SequencerClientInner {
sequencer_endpoint: sequencer_endpoint.into(),
http_client,
id: AtomicUsize::new(0),
};
Self { inner: Arc::new(inner) }
}
/// Returns the network of the client
pub fn endpoint(&self) -> &str {
&self.inner.sequencer_endpoint
}
/// Returns the client
pub fn http_client(&self) -> &Client {
&self.inner.http_client
}
/// Returns the next id for the request
fn next_request_id(&self) -> usize {
self.inner.id.fetch_add(1, std::sync::atomic::Ordering::SeqCst)
}
/// Forwards a transaction to the sequencer endpoint.
pub async fn forward_raw_transaction(&self, tx: &[u8]) -> Result<(), SequencerRpcError> {
let body = serde_json::to_string(&serde_json::json!({
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [format!("0x{}", reth_primitives::hex::encode(tx))],
"id": self.next_request_id()
}))
.map_err(|_| {
tracing::warn!(
target = "rpc::eth",
"Failed to serialize transaction for forwarding to sequencer"
);
SequencerRpcError::InvalidSequencerTransaction
})?;
self.http_client()
.post(self.endpoint())
.header(http::header::CONTENT_TYPE, "application/json")
.body(body)
.send()
.await
.map_err(SequencerRpcError::HttpError)?;
Ok(())
}
}
#[async_trait::async_trait]
impl RawTransactionForwarder for SequencerClient {
async fn forward_raw_transaction(&self, tx: &[u8]) -> EthResult<()> {
SequencerClient::forward_raw_transaction(self, tx).await?;
Ok(())
}
}
#[derive(Debug, Default)]
struct SequencerClientInner {
/// The endpoint of the sequencer
sequencer_endpoint: String,
/// The HTTP client
http_client: Client,
/// Keeps track of unique request ids
id: AtomicUsize,
}

View File

@ -87,6 +87,7 @@ where
BlockingTaskPool::build().expect("failed to build tracing pool"),
fee_history_cache,
evm_config,
None,
);
let config = EthFilterConfig::default()
.max_logs_per_response(DEFAULT_MAX_LOGS_PER_RESPONSE)

View File

@ -27,7 +27,7 @@ pub struct EthHandlers<Provider, Pool, Network, Events, EvmConfig> {
pub blocking_task_pool: BlockingTaskPool,
}
/// Additional config values for the eth namespace
/// Additional config values for the eth namespace.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct EthConfig {
/// Settings for the caching layer

View File

@ -180,6 +180,7 @@ use reth_rpc::{
cache::{cache_new_blocks_task, EthStateCache},
fee_history_cache_new_blocks_task,
gas_oracle::GasPriceOracle,
traits::RawTransactionForwarder,
EthBundle, FeeHistoryCache,
},
AdminApi, AuthLayer, Claims, DebugApi, EngineEthApi, EthApi, EthFilter, EthPubSub,
@ -198,6 +199,7 @@ use std::{
fmt,
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
str::FromStr,
sync::Arc,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use strum::{AsRefStr, EnumIter, IntoStaticStr, ParseError, VariantArray, VariantNames};
@ -949,6 +951,9 @@ pub struct RethModuleRegistry<Provider, Pool, Network, Tasks, Events, EvmConfig>
blocking_pool_guard: BlockingTaskGuard,
/// Contains the [Methods] of a module
modules: HashMap<RethRpcModule, Methods>,
/// Optional forwarder for `eth_sendRawTransaction`
// TODO(mattsse): find a more ergonomic way to configure eth/rpc customizations
eth_raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
}
// === impl RethModuleRegistry ===
@ -977,9 +982,20 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
blocking_pool_guard: BlockingTaskGuard::new(config.eth.max_tracing_requests),
config,
events,
eth_raw_transaction_forwarder: None,
}
}
/// Sets a forwarder for `eth_sendRawTransaction`
///
/// Note: this might be removed in the future in favor of a more generic approach.
pub fn set_eth_raw_transaction_forwarder(
&mut self,
forwarder: Arc<dyn RawTransactionForwarder>,
) {
self.eth_raw_transaction_forwarder = Some(forwarder);
}
/// Returns a reference to the pool
pub fn pool(&self) -> &Pool {
&self.pool
@ -1331,6 +1347,7 @@ where
blocking_task_pool.clone(),
fee_history_cache,
self.evm_config.clone(),
self.eth_raw_transaction_forwarder.clone(),
);
let filter = EthFilter::new(
self.provider.clone(),

View File

@ -47,11 +47,6 @@ http-body = "0.4.5"
hyper.workspace = true
jsonwebtoken = "8"
## required for optimism sequencer delegation
reqwest = { version = "0.11", default-features = false, features = [
"rustls-tls",
], optional = true }
# async
async-trait.workspace = true
tokio = { workspace = true, features = ["sync"] }
@ -90,9 +85,7 @@ reth-interfaces = { workspace = true, features = ["test-utils"] }
[features]
optimism = [
"dep:reqwest",
"reth-primitives/optimism",
"reth-rpc-types-compat/optimism",
"reth-network-api/optimism",
"reth-provider/optimism",
]

View File

@ -49,6 +49,7 @@ mod sign;
mod state;
mod transactions;
use crate::eth::traits::RawTransactionForwarder;
pub use transactions::{EthTransactions, TransactionSource};
/// `Eth` API trait.
@ -104,6 +105,7 @@ where
blocking_task_pool: BlockingTaskPool,
fee_history_cache: FeeHistoryCache,
evm_config: EvmConfig,
raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
) -> Self {
Self::with_spawner(
provider,
@ -116,6 +118,7 @@ where
blocking_task_pool,
fee_history_cache,
evm_config,
raw_transaction_forwarder,
)
}
@ -132,6 +135,7 @@ where
blocking_task_pool: BlockingTaskPool,
fee_history_cache: FeeHistoryCache,
evm_config: EvmConfig,
raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
) -> Self {
// get the block number of the latest block
let latest_block = provider
@ -155,8 +159,7 @@ where
blocking_task_pool,
fee_history_cache,
evm_config,
#[cfg(feature = "optimism")]
http_client: reqwest::Client::builder().use_rustls_tls().build().unwrap(),
raw_transaction_forwarder,
};
Self { inner: Arc::new(inner) }
@ -486,7 +489,6 @@ struct EthApiInner<Provider, Pool, Network, EvmConfig> {
fee_history_cache: FeeHistoryCache,
/// The type that defines how to configure the EVM
evm_config: EvmConfig,
/// An http client for communicating with sequencers.
#[cfg(feature = "optimism")]
http_client: reqwest::Client,
/// Allows forwarding received raw transactions
raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
}

View File

@ -486,6 +486,7 @@ mod tests {
BlockingTaskPool::build().expect("failed to build tracing pool"),
fee_history_cache,
evm_config,
None,
)
}

View File

@ -145,6 +145,7 @@ mod tests {
BlockingTaskPool::build().expect("failed to build tracing pool"),
FeeHistoryCache::new(cache, FeeHistoryCacheConfig::default()),
evm_config,
None,
);
let address = Address::random();
let storage = eth_api.storage_at(address, U256::ZERO.into(), None).unwrap();
@ -169,6 +170,7 @@ mod tests {
BlockingTaskPool::build().expect("failed to build tracing pool"),
FeeHistoryCache::new(cache, FeeHistoryCacheConfig::default()),
evm_config,
None,
);
let storage_key: U256 = storage_key.into();

View File

@ -848,8 +848,10 @@ where
async fn send_raw_transaction(&self, tx: Bytes) -> EthResult<B256> {
// On optimism, transactions are forwarded directly to the sequencer to be included in
// blocks that it builds.
#[cfg(feature = "optimism")]
self.forward_to_sequencer(&tx).await?;
if let Some(client) = self.inner.raw_transaction_forwarder.as_ref() {
tracing::debug!( target: "rpc::eth", "forwarding raw transaction to");
client.forward_raw_transaction(&tx).await?;
}
let recovered = recover_raw_transaction(tx)?;
let pool_transaction = <Pool::Transaction>::from_recovered_pooled_transaction(recovered);
@ -1506,39 +1508,6 @@ where
Ok(OptimismTxMeta::new(Some(l1_block_info), l1_fee, l1_data_gas))
}
/// Helper function for `eth_sendRawTransaction` for Optimism.
///
/// Forwards the raw transaction bytes to the configured sequencer endpoint.
/// This is a no-op if the sequencer endpoint is not configured.
#[cfg(feature = "optimism")]
pub async fn forward_to_sequencer(&self, tx: &Bytes) -> EthResult<()> {
if let Some(endpoint) = self.network().sequencer_endpoint() {
let body = serde_json::to_string(&serde_json::json!({
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [format!("0x{}", alloy_primitives::hex::encode(tx))],
"id": self.network().chain_id()
}))
.map_err(|_| {
tracing::warn!(
target = "rpc::eth",
"Failed to serialize transaction for forwarding to sequencer"
);
OptimismEthApiError::InvalidSequencerTransaction
})?;
self.inner
.http_client
.post(endpoint)
.header(http::header::CONTENT_TYPE, "application/json")
.body(body)
.send()
.await
.map_err(OptimismEthApiError::HttpError)?;
}
Ok(())
}
}
impl<Provider, Pool, Network, EvmConfig> EthApi<Provider, Pool, Network, EvmConfig>
@ -1843,6 +1812,7 @@ mod tests {
BlockingTaskPool::build().expect("failed to build tracing pool"),
fee_history_cache,
evm_config,
None,
);
// https://etherscan.io/tx/0xa694b71e6c128a2ed8e2e0f6770bddbe52e3bb8f10e8472f9a79ab81497a8b5d

View File

@ -11,6 +11,7 @@ mod logs_utils;
mod pubsub;
pub mod revm_utils;
mod signer;
pub mod traits;
pub(crate) mod utils;
#[cfg(feature = "optimism")]

View File

@ -1,25 +1,16 @@
//! Optimism specific types.
use jsonrpsee::types::ErrorObject;
use crate::{
eth::error::{EthApiError, ToRpcError},
result::internal_rpc_err,
};
use jsonrpsee::types::ErrorObject;
use reqwest::Client;
/// Eth Optimism Api Error
#[cfg(feature = "optimism")]
#[derive(Debug, thiserror::Error)]
pub enum OptimismEthApiError {
/// Wrapper around a [hyper::Error].
#[error(transparent)]
HyperError(#[from] hyper::Error),
/// Wrapper around an [reqwest::Error].
#[error(transparent)]
HttpError(#[from] reqwest::Error),
/// Thrown when serializing transaction to forward to sequencer
#[error("invalid sequencer transaction")]
InvalidSequencerTransaction,
/// Thrown when calculating L1 gas fee
#[error("failed to calculate l1 gas fee")]
L1BlockFeeError,
@ -31,11 +22,9 @@ pub enum OptimismEthApiError {
impl ToRpcError for OptimismEthApiError {
fn to_rpc_error(&self) -> ErrorObject<'static> {
match self {
OptimismEthApiError::HyperError(err) => internal_rpc_err(err.to_string()),
OptimismEthApiError::HttpError(err) => internal_rpc_err(err.to_string()),
OptimismEthApiError::InvalidSequencerTransaction |
OptimismEthApiError::L1BlockFeeError |
OptimismEthApiError::L1BlockGasError => internal_rpc_err(self.to_string()),
OptimismEthApiError::L1BlockFeeError | OptimismEthApiError::L1BlockGasError => {
internal_rpc_err(self.to_string())
}
}
}
}
@ -45,19 +34,3 @@ impl From<OptimismEthApiError> for EthApiError {
EthApiError::other(err)
}
}
/// A client to interact with a Sequencer
#[derive(Debug, Default, Clone)]
pub struct SequencerClient {
/// The endpoint of the sequencer
pub sequencer_endpoint: String,
/// The HTTP client
pub http_client: Client,
}
impl SequencerClient {
/// Creates a new [SequencerClient].
pub fn new(sequencer_endpoint: impl Into<String>, http_client: Client) -> Self {
Self { sequencer_endpoint: sequencer_endpoint.into(), http_client }
}
}

View File

@ -0,0 +1,13 @@
//! Additional helper traits that allow for more customization.
use crate::eth::error::EthResult;
use std::fmt;
/// A trait that allows for forwarding raw transactions.
///
/// For example to a sequencer.
#[async_trait::async_trait]
pub trait RawTransactionForwarder: fmt::Debug + Send + Sync + 'static {
/// Forwards raw transaction bytes for `eth_sendRawTransaction`
async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()>;
}

View File

@ -159,7 +159,6 @@ where
#[cfg(test)]
mod tests {
use http::{header, Method, Request, StatusCode};
use hyper::{body, Body};
use jsonrpsee::{