diff --git a/src/proxy.rs b/src/proxy.rs index 2e8f80b..3b1c674 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -9,6 +9,8 @@ use std::{future::Future, pin::Pin}; use tower::{Layer, Service}; use tracing::debug; +const MULTIPLEX_METHODS: [&str; 2] = ["engine_", "eth_sendRawTransaction"]; + #[derive(Debug, Clone)] pub struct ProxyLayer { target_url: Uri, @@ -84,7 +86,7 @@ where message = "received json rpc request for", method = method.method ); - if method.method.starts_with("engine_") { + if PROXY_METHODS.iter().any(|&m| method.method.starts_with(m)) { // let rpc server handle engine rpc requests let res = inner.call(req).await.map_err(|e| e.into())?; Ok(res) diff --git a/src/server.rs b/src/server.rs index 3190e2f..4fcb125 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,4 +1,5 @@ use alloy::primitives::B256; +use alloy_primitives::Bytes; use alloy_rpc_types_engine::{ ExecutionPayload, ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, @@ -14,7 +15,7 @@ use op_alloy_rpc_types_engine::{ }; use reth_rpc_layer::AuthClientService; use std::sync::Arc; -use tracing::{error, info}; +use tracing::{debug, error, info}; #[rpc(server, client, namespace = "engine")] pub trait EngineApi { @@ -40,6 +41,12 @@ pub trait EngineApi { ) -> RpcResult; } +#[rpc(server, client, namespace = "eth")] +pub trait EthApi { + #[method(name = "sendRawTransaction")] + async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult; +} + pub struct EthEngineApi> { l2_client: Arc>, builder_client: Arc>, @@ -60,6 +67,36 @@ impl EthEngineApi { } } +#[async_trait] +impl EthApiServer for EthEngineApi { + async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult { + debug!( + message = "received send_raw_transaction", + "bytes_len" = bytes.len() + ); + let builder = self.builder_client.clone(); + let tx_bytes = bytes.clone(); + tokio::spawn(async move { + builder.send_raw_transaction(tx_bytes).await.map_err(|e| { + error!(message = "error calling send_raw_transaction for builder", "error" = %e); + }) + }); + self.l2_client + .send_raw_transaction(bytes) + .await + .map_err(|e| match e { + ClientError::Call(err) => err, // Already an ErrorObjectOwned, so just return it + other_error => { + error!( + message = "error calling send_raw_transaction for l2 client", + "error" = %other_error, + ); + ErrorCode::InternalError.into() + } + }) + } +} + #[async_trait] impl EngineApiServer for EthEngineApi { async fn fork_choice_updated_v3(