Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions crates/op-rbuilder/src/launcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
metrics::{record_flag_gauge_metrics, VERSION},
monitor_tx_pool::monitor_tx_pool,
primitives::reth::engine_api_builder::OpEngineApiBuilder,
revert_protection::{EthApiExtServer, EthApiOverrideServer, RevertProtectionExt},
revert_protection::{EthApiExtServer, RevertProtectionExt},
tx::FBPooledTransaction,
};
use core::fmt::Debug;
Expand Down Expand Up @@ -149,14 +149,15 @@ where

let pool = ctx.pool().clone();
let provider = ctx.provider().clone();
let revert_protection_ext =
RevertProtectionExt::new(pool, provider, ctx.registry.eth_api().clone());
let revert_protection_ext = RevertProtectionExt::new(
pool,
provider,
ctx.registry.eth_api().clone(),
reverted_cache,
);

ctx.modules
.merge_configured(revert_protection_ext.bundle_api().into_rpc())?;
ctx.modules.replace_configured(
revert_protection_ext.eth_api(reverted_cache).into_rpc(),
)?;
.add_or_replace_configured(revert_protection_ext.into_rpc())?;
}

Ok(())
Expand Down
96 changes: 33 additions & 63 deletions crates/op-rbuilder/src/revert_protection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,13 @@ use reth_rpc_eth_types::{utils::recover_raw_transaction, EthApiError};
use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool};
use tracing::error;

// We have to split the RPC modules in two sets because we have methods that both
// replace an existing method and add a new one.
// Tracking change in Reth here to have a single method for both:
// https://github.com/paradigmxyz/reth/issues/16502

// Namespace overrides for revert protection support
#[cfg_attr(not(test), rpc(server, namespace = "eth"))]
#[cfg_attr(test, rpc(server, client, namespace = "eth"))]
pub trait EthApiExt {
pub trait EthApiExt<R: RpcObject> {
#[method(name = "sendBundle")]
async fn send_bundle(&self, tx: Bundle) -> RpcResult<BundleResult>;
}

#[rpc(server, client, namespace = "eth")]
pub trait EthApiOverride<R: RpcObject> {
#[method(name = "getTransactionReceipt")]
async fn transaction_receipt(&self, hash: B256) -> RpcResult<Option<R>>;
}
Expand All @@ -43,6 +35,7 @@ pub struct RevertProtectionExt<Pool, Provider, Eth> {
provider: Provider,
eth_api: Eth,
metrics: Arc<OpRBuilderMetrics>,
reverted_cache: Cache<B256, ()>,
}

impl<Pool, Provider, Eth> RevertProtectionExt<Pool, Provider, Eth>
Expand All @@ -51,42 +44,29 @@ where
Provider: Clone,
Eth: Clone,
{
pub fn new(pool: Pool, provider: Provider, eth_api: Eth) -> Self {
pub fn new(
pool: Pool,
provider: Provider,
eth_api: Eth,
reverted_cache: Cache<B256, ()>,
) -> Self {
Self {
pool,
provider,
eth_api,
metrics: Arc::new(OpRBuilderMetrics::default()),
}
}

pub fn bundle_api(&self) -> RevertProtectionBundleAPI<Pool, Provider> {
RevertProtectionBundleAPI {
pool: self.pool.clone(),
provider: self.provider.clone(),
metrics: self.metrics.clone(),
}
}

pub fn eth_api(&self, reverted_cache: Cache<B256, ()>) -> RevertProtectionEthAPI<Eth> {
RevertProtectionEthAPI {
eth_api: self.eth_api.clone(),
reverted_cache,
}
}
}

pub struct RevertProtectionBundleAPI<Pool, Provider> {
pool: Pool,
provider: Provider,
metrics: Arc<OpRBuilderMetrics>,
}

#[async_trait]
impl<Pool, Provider> EthApiExtServer for RevertProtectionBundleAPI<Pool, Provider>
impl<Pool, Provider, Eth> EthApiExtServer<RpcReceipt<Eth::NetworkTypes>>
for RevertProtectionExt<Pool, Provider, Eth>
where
Pool: TransactionPool<Transaction = FBPooledTransaction> + Clone + 'static,
Provider: StateProviderFactory + Send + Sync + Clone + 'static,
Eth: FullEthApi + Send + Sync + Clone + 'static,
{
async fn send_bundle(&self, bundle: Bundle) -> RpcResult<BundleResult> {
let request_start_time = Instant::now();
Expand All @@ -109,12 +89,33 @@ where

bundle_result
}

async fn transaction_receipt(
&self,
hash: B256,
) -> RpcResult<Option<RpcReceipt<Eth::NetworkTypes>>> {
match self.eth_api.transaction_receipt(hash).await.unwrap() {
Some(receipt) => Ok(Some(receipt)),
None => {
// Try to find the transaction in the reverted cache
if self.reverted_cache.get(&hash).await.is_some() {
return Err(EthApiError::InvalidParams(
"the transaction was dropped from the pool".into(),
)
.into());
} else {
return Ok(None);
}
}
}
}
}

impl<Pool, Provider> RevertProtectionBundleAPI<Pool, Provider>
impl<Pool, Provider, Eth> RevertProtectionExt<Pool, Provider, Eth>
where
Pool: TransactionPool<Transaction = FBPooledTransaction> + Clone + 'static,
Provider: StateProviderFactory + Send + Sync + Clone + 'static,
Eth: FullEthApi + Send + Sync + Clone + 'static,
{
async fn send_bundle_inner(&self, bundle: Bundle) -> RpcResult<BundleResult> {
let last_block_number = self
Expand Down Expand Up @@ -161,34 +162,3 @@ where
Ok(result)
}
}

pub struct RevertProtectionEthAPI<Eth> {
eth_api: Eth,
reverted_cache: Cache<B256, ()>,
}

#[async_trait]
impl<Eth> EthApiOverrideServer<RpcReceipt<Eth::NetworkTypes>> for RevertProtectionEthAPI<Eth>
where
Eth: FullEthApi + Send + Sync + Clone + 'static,
{
async fn transaction_receipt(
&self,
hash: B256,
) -> RpcResult<Option<RpcReceipt<Eth::NetworkTypes>>> {
match self.eth_api.transaction_receipt(hash).await.unwrap() {
Some(receipt) => Ok(Some(receipt)),
None => {
// Try to find the transaction in the reverted cache
if self.reverted_cache.get(&hash).await.is_some() {
return Err(EthApiError::InvalidParams(
"the transaction was dropped from the pool".into(),
)
.into());
} else {
return Ok(None);
}
}
}
}
}
16 changes: 8 additions & 8 deletions crates/op-rbuilder/src/tests/framework/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
args::OpRbuilderArgs,
builders::{BuilderConfig, FlashblocksBuilder, PayloadBuilder, StandardBuilder},
primitives::reth::engine_api_builder::OpEngineApiBuilder,
revert_protection::{EthApiExtServer, EthApiOverrideServer, RevertProtectionExt},
revert_protection::{EthApiExtServer, RevertProtectionExt},
tests::{
create_test_db,
framework::{driver::ChainDriver, BUILDER_PRIVATE_KEY},
Expand Down Expand Up @@ -126,15 +126,15 @@ impl LocalInstance {

let pool = ctx.pool().clone();
let provider = ctx.provider().clone();
let revert_protection_ext =
RevertProtectionExt::new(pool, provider, ctx.registry.eth_api().clone());
let revert_protection_ext = RevertProtectionExt::new(
pool,
provider,
ctx.registry.eth_api().clone(),
reverted_cache,
);

ctx.modules
.merge_configured(revert_protection_ext.bundle_api().into_rpc())?;

ctx.modules.replace_configured(
revert_protection_ext.eth_api(reverted_cache).into_rpc(),
)?;
.add_or_replace_configured(revert_protection_ext.into_rpc())?;
}

Ok(())
Expand Down
Loading