From 5986c116ee7a7ee312bd93773063016d270d8494 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:34:59 -0300 Subject: [PATCH 01/30] Changes to allow easier testing in bidding. (#163) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to allow easier testing in bidding. Decoupled BestBidSource from SlotBidder. ## 📝 Summary These are really simple changes: - Added some #[automock] to traits. - Created a Mock BlockBuildingHelper to play with block flow without having blocks. - Decoupled BestBidSource from SlotBidder since it was only used on the relay submit. ## 💡 Motivation and Context Any programmer making a real bidder would struggle without this stuff. ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable) --- .../builders/block_building_helper.rs | 8 +- .../builders/mock_block_building_helper.rs | 103 ++++++++++++++++++ crates/rbuilder/src/building/builders/mod.rs | 1 + crates/rbuilder/src/building/mod.rs | 15 +++ .../live_builder/block_output/bidding/mod.rs | 7 -- .../block_output/block_finisher_factory.rs | 4 +- .../live_builder/block_output/relay_submit.rs | 32 ++++-- crates/rbuilder/src/live_builder/config.rs | 31 ++---- 8 files changed, 163 insertions(+), 38 deletions(-) create mode 100644 crates/rbuilder/src/building/builders/mock_block_building_helper.rs diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index e8fa537b..e15bfa03 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -34,7 +34,9 @@ use super::Block; /// 2 - Call lots of commit_order. /// 3 - Call set_trace_fill_time when you are done calling commit_order (we still have to review this step). /// 4 - Call finalize_block. -pub trait BlockBuildingHelper { +pub trait BlockBuildingHelper: Send { + fn box_clone(&self) -> Box; + /// Tries to add an order to the end of the block. /// Block state changes only on Ok(Ok) fn commit_order( @@ -380,4 +382,8 @@ impl BlockBuildingHelper for BlockBuildingHelper fn building_context(&self) -> &BlockBuildingContext { &self.building_ctx } + + fn box_clone(&self) -> Box { + Box::new(self.clone()) + } } diff --git a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs new file mode 100644 index 00000000..e0f295a1 --- /dev/null +++ b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs @@ -0,0 +1,103 @@ +use crate::{ + building::{ + BlockBuildingContext, BuiltBlockTrace, CriticalCommitOrderError, ExecutionError, + ExecutionResult, + }, + primitives::SimulatedOrder, +}; +use alloy_primitives::U256; +use reth_payload_builder::database::CachedReads; +use reth_primitives::SealedBlock; +use time::OffsetDateTime; + +use super::{ + block_building_helper::{BlockBuildingHelper, BlockBuildingHelperError, FinalizeBlockResult}, + Block, +}; + +/// Extremely dumb object for test. Adding orders (commit_order) is not allowed. +/// Is has a predefined true_block_value and the only useful thing that generates on finalize_block is the bid value. +#[derive(Clone, Debug)] +pub struct MockBlockBuildingHelper { + built_block_trace: BuiltBlockTrace, + block_building_context: BlockBuildingContext, + can_add_payout_tx: bool, +} + +impl MockBlockBuildingHelper { + pub fn new(true_block_value: U256, can_add_payout_tx: bool) -> Self { + let built_block_trace = BuiltBlockTrace { + true_bid_value: true_block_value, + ..Default::default() + }; + Self { + built_block_trace, + block_building_context: BlockBuildingContext::dummy_for_testing(), + can_add_payout_tx, + } + } +} + +impl BlockBuildingHelper for MockBlockBuildingHelper { + fn box_clone(&self) -> Box { + Box::new(self.clone()) + } + + fn commit_order( + &mut self, + _order: &SimulatedOrder, + ) -> Result, CriticalCommitOrderError> { + unimplemented!() + } + + fn set_trace_fill_time(&mut self, time: std::time::Duration) { + self.built_block_trace.fill_time = time; + } + + fn set_trace_orders_closed_at(&mut self, orders_closed_at: OffsetDateTime) { + self.built_block_trace.orders_closed_at = orders_closed_at; + } + + fn can_add_payout_tx(&self) -> bool { + self.can_add_payout_tx + } + + fn true_block_value(&self) -> Result { + Ok(self.built_block_trace.true_bid_value) + } + + fn finalize_block( + mut self: Box, + payout_tx_value: Option, + ) -> Result { + self.built_block_trace.update_orders_sealed_at(); + self.built_block_trace.bid_value = if let Some(payout_tx_value) = payout_tx_value { + payout_tx_value + } else { + self.built_block_trace.true_bid_value + }; + let block = Block { + trace: self.built_block_trace, + sealed_block: SealedBlock::default(), + txs_blobs_sidecars: Vec::new(), + builder_name: "BlockBuildingHelper".to_string(), + }; + + Ok(FinalizeBlockResult { + block, + cached_reads: CachedReads::default(), + }) + } + + fn clone_cached_reads(&self) -> CachedReads { + CachedReads::default() + } + + fn built_block_trace(&self) -> &BuiltBlockTrace { + &self.built_block_trace + } + + fn building_context(&self) -> &BlockBuildingContext { + &self.block_building_context + } +} diff --git a/crates/rbuilder/src/building/builders/mod.rs b/crates/rbuilder/src/building/builders/mod.rs index ac1158fb..c5826053 100644 --- a/crates/rbuilder/src/building/builders/mod.rs +++ b/crates/rbuilder/src/building/builders/mod.rs @@ -1,5 +1,6 @@ //! builders is a subprocess that builds a block pub mod block_building_helper; +pub mod mock_block_building_helper; pub mod ordering_builder; use crate::{ diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index 7e8332e0..6d65a925 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -228,6 +228,21 @@ impl BlockBuildingContext { } } + /// Useless BlockBuildingContext for testing in contexts where we can't avoid having a BlockBuildingContext. + pub fn dummy_for_testing() -> Self { + let mut onchain_block = alloy_rpc_types::Block::default(); + onchain_block.header.base_fee_per_gas = Some(0); + BlockBuildingContext::from_onchain_block( + onchain_block, + reth_chainspec::MAINNET.clone(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ) + } + pub fn modify_use_suggested_fee_recipient_as_coinbase(&mut self) { self.builder_signer = None; self.block_env.coinbase = self.attributes.suggested_fee_recipient; diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs b/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs index 086707ed..404f4780 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs @@ -22,9 +22,6 @@ pub trait SlotBidder: Send + Sync + std::fmt::Debug { unsealed_block_profit: U256, slot_timestamp: time::OffsetDateTime, ) -> SealInstruction; - - /// Returns best bid value available on the relays. - fn best_bid_value(&self) -> Option; } impl SlotBidder for () { @@ -39,10 +36,6 @@ impl SlotBidder for () { ) -> SealInstruction { SealInstruction::Value(unsealed_block_profit) } - - fn best_bid_value(&self) -> Option { - None - } } pub trait BiddingService: std::fmt::Debug + Send + Sync { diff --git a/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs b/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs index b30f3d51..2f5daf92 100644 --- a/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs +++ b/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs @@ -10,7 +10,7 @@ use crate::{ use super::{ bidding::{BiddingService, SlotBidder}, block_finisher::BlockFinisher, - relay_submit::BuilderSinkFactory, + relay_submit::{BuilderSinkFactory, NullBestBidSource}, }; #[derive(Debug)] @@ -45,7 +45,7 @@ impl UnfinishedBlockBuildingSinkFactory for BlockFinisherFactory { ); let finished_block_sink = self.block_sink_factory.create_builder_sink( slot_data, - slot_bidder.clone(), + Arc::new(NullBestBidSource {}), cancel.clone(), ); diff --git a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs index 5cce61f3..9504a15c 100644 --- a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs +++ b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs @@ -17,6 +17,7 @@ use crate::{ }; use ahash::HashMap; use alloy_primitives::{utils::format_ether, U256}; +use mockall::automock; use reth_chainspec::ChainSpec; use reth_primitives::SealedBlock; use std::{ @@ -27,8 +28,6 @@ use tokio::time::{sleep, Instant}; use tokio_util::sync::CancellationToken; use tracing::{debug, error, info_span, trace, warn, Instrument}; -use super::bidding::SlotBidder; - const SIM_ERROR_CATEGORY: &str = "submit_block_simulation"; const VALIDATION_ERROR_CATEGORY: &str = "validate_block_simulation"; @@ -71,10 +70,25 @@ impl BestBlockCell { } /// Final destination of blocks (eg: submit to the relays). +#[automock] pub trait BlockBuildingSink: std::fmt::Debug + Send + Sync { fn new_block(&self, block: Block); } +/// trait to get the best bid from the competition. +/// Used only by BuilderSinkFactory. +pub trait BestBidSource: Send + Sync { + fn best_bid_value(&self) -> Option; +} + +pub struct NullBestBidSource {} + +impl BestBidSource for NullBestBidSource { + fn best_bid_value(&self) -> Option { + None + } +} + /// Factory used to create BlockBuildingSink.. pub trait BuilderSinkFactory: std::fmt::Debug + Send + Sync { /// # Arguments @@ -82,7 +96,7 @@ pub trait BuilderSinkFactory: std::fmt::Debug + Send + Sync { fn create_builder_sink( &self, slot_data: MevBoostSlotData, - slot_bidder: Arc, + bid_source: Arc, cancel: CancellationToken, ) -> Box; } @@ -131,7 +145,7 @@ async fn run_submit_to_relays_job( relays: Vec, config: SubmissionConfig, cancel: CancellationToken, - slot_bidder: Arc, + bid_source: Arc, ) -> Option { let mut res = None; // first, sleep to slot time - slot_delta_to_start_submits @@ -195,7 +209,7 @@ async fn run_submit_to_relays_job( .count(); let submission_optimistic = config.optimistic_enabled && block.trace.bid_value < config.optimistic_max_bid_value; - let best_bid_value = slot_bidder.best_bid_value().unwrap_or_default(); + let best_bid_value = bid_source.best_bid_value().unwrap_or_default(); let submission_span = info_span!( "bid", bid_value = format_ether(block.trace.bid_value), @@ -387,7 +401,7 @@ pub async fn run_submit_to_relays_job_and_metrics( relays: Vec, config: SubmissionConfig, cancel: CancellationToken, - slot_bidder: Arc, + bid_source: Arc, ) { let best_bid = run_submit_to_relays_job( best_bid.clone(), @@ -395,7 +409,7 @@ pub async fn run_submit_to_relays_job_and_metrics( relays, config, cancel, - slot_bidder, + bid_source, ) .await; if let Some(best_bid) = best_bid { @@ -527,7 +541,7 @@ impl BuilderSinkFactory for RelaySubmitSinkFactory { fn create_builder_sink( &self, slot_data: MevBoostSlotData, - slot_bidder: Arc, + bid_source: Arc, cancel: CancellationToken, ) -> Box { let best_bid = BestBlockCell::default(); @@ -548,7 +562,7 @@ impl BuilderSinkFactory for RelaySubmitSinkFactory { relays, self.submission_config.clone(), cancel, - slot_bidder, + bid_source, )); Box::new(best_bid) } diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index c053c71e..1c4b5c40 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -3,10 +3,7 @@ //! use super::{ base_config::BaseConfig, - block_output::{ - bidding::BiddingService, - relay_submit::{RelaySubmitSinkFactory, SubmissionConfig}, - }, + block_output::relay_submit::{RelaySubmitSinkFactory, SubmissionConfig}, }; use crate::{ beacon_api_client::Client, @@ -14,7 +11,6 @@ use crate::{ builders::{ ordering_builder::{OrderingBuilderConfig, OrderingBuildingAlgorithm}, BacktestSimulateBlockInput, Block, BlockBuildingAlgorithm, - UnfinishedBlockBuildingSinkFactory, }, Sorting, }, @@ -240,15 +236,11 @@ impl L1Config { }) } - /// Creates the RelaySubmitSinkFactory and also returns the asociated relays. - pub fn create_relays_sink_factory( + /// Creates the RelaySubmitSinkFactory and also returns the associated relays. + pub fn create_relays_sealed_sink_factory( &self, chain_spec: Arc, - bidding_service: Box, - ) -> eyre::Result<( - Box, - Vec, - )> { + ) -> eyre::Result<(Box, Vec)> { let submission_config = self.submission_config(chain_spec)?; info!( "Builder mev boost normal relay pubkey: {:?}", @@ -270,10 +262,7 @@ impl L1Config { submission_config, relays.clone(), )); - Ok(( - Box::new(BlockFinisherFactory::new(bidding_service, sink_factory)), - relays, - )) + Ok((sink_factory, relays)) } } @@ -286,10 +275,14 @@ impl LiveBuilderConfig for Config { &self, cancellation_token: tokio_util::sync::CancellationToken, ) -> eyre::Result, MevBoostSlotDataGenerator>> { - let (sink_factory, relays) = self.l1_config.create_relays_sink_factory( - self.base_config.chain_spec()?, + let (sink_sealed_factory, relays) = self + .l1_config + .create_relays_sealed_sink_factory(self.base_config.chain_spec()?)?; + let sink_factory = Box::new(BlockFinisherFactory::new( Box::new(DummyBiddingService {}), - )?; + sink_sealed_factory, + )); + let payload_event = MevBoostSlotDataGenerator::new( self.l1_config.beacon_clients()?, relays, From c78f4a9e0a8eb7fea94a43cfdc1c5ba421ac58b6 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:08:22 -0300 Subject: [PATCH 02/30] Remove tx default debug (#166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This PR tries to minimize the access to TransactionSignedEcRecoveredWithBlobs::tx to avoid leaking information by mistake: - tx is not pub anymore. - Replaced the default fmt::Debug implementation for just the hash. - Removed unnecessary AsRef ## 💡 Motivation and Context We are trying to avoid leaking tx info for future TEE deployments. ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable) --- .../src/backtest/backtest_build_block.rs | 9 ++-- .../rbuilder/src/backtest/redistribute/mod.rs | 8 +-- .../find_landed_orders.rs | 2 +- .../resim_landed_block.rs | 14 +++-- .../rbuilder/src/bin/debug-bench-machine.rs | 6 +-- .../src/building/built_block_trace.rs | 1 - crates/rbuilder/src/building/mod.rs | 16 +++--- crates/rbuilder/src/building/order_commit.rs | 24 +++++---- .../order_input/txpool_fetcher.rs | 4 +- crates/rbuilder/src/primitives/mod.rs | 52 +++++++++++++++---- crates/rbuilder/src/utils/test_utils.rs | 9 ++-- 11 files changed, 88 insertions(+), 57 deletions(-) diff --git a/crates/rbuilder/src/backtest/backtest_build_block.rs b/crates/rbuilder/src/backtest/backtest_build_block.rs index e8ed3b62..36a7e94f 100644 --- a/crates/rbuilder/src/backtest/backtest_build_block.rs +++ b/crates/rbuilder/src/backtest/backtest_build_block.rs @@ -243,8 +243,7 @@ fn print_order_and_timestamp(orders_with_ts: &[OrdersWithTimestamp], block_data: ) ); for (tx, optional) in owt.order.list_txs() { - let tx = &tx.tx; - println!(" {:?} {:?}", tx.hash, optional); + println!(" {:?} {:?}", tx.hash(), optional); println!( " from: {:?} to: {:?} nonce: {}", tx.signer(), @@ -326,7 +325,7 @@ fn print_onchain_block_data( let txs_to_idx: HashMap<_, _> = tx_sim_results .iter() .enumerate() - .map(|(idx, tx)| (tx.tx.hash(), idx)) + .map(|(idx, tx)| (tx.hash(), idx)) .collect(); println!("Onchain block txs:"); @@ -334,7 +333,7 @@ fn print_onchain_block_data( println!( "{:>4}, {:>74} revert: {:>5} profit: {}", idx, - tx.tx.hash(), + tx.hash(), !tx.receipt.success, format_ether(tx.coinbase_profit) ); @@ -352,7 +351,7 @@ fn print_onchain_block_data( } } executed_orders.push(ExecutedBlockTx::new( - tx.tx.hash, + tx.hash(), tx.coinbase_profit, tx.receipt.success, )) diff --git a/crates/rbuilder/src/backtest/redistribute/mod.rs b/crates/rbuilder/src/backtest/redistribute/mod.rs index 196543a3..65953c55 100644 --- a/crates/rbuilder/src/backtest/redistribute/mod.rs +++ b/crates/rbuilder/src/backtest/redistribute/mod.rs @@ -247,7 +247,7 @@ fn restore_available_landed_orders( .into_iter() .map(|executed_tx| { ExecutedBlockTx::new( - executed_tx.tx.hash, + executed_tx.hash(), executed_tx.coinbase_profit, executed_tx.receipt.success, ) @@ -949,7 +949,7 @@ fn order_redistribution_address(order: &Order, protect_signers: &[Address]) -> O Some(signer) => signer, None => { return if order.is_tx() { - Some(order.list_txs().first()?.0.tx.signer()) + Some(order.list_txs().first()?.0.signer()) } else { None } @@ -964,7 +964,7 @@ fn order_redistribution_address(order: &Order, protect_signers: &[Address]) -> O Order::Bundle(bundle) => { // if its just a bundle we take origin tx of the first transaction let tx = bundle.txs.first()?; - Some(tx.tx.signer()) + Some(tx.signer()) } Order::ShareBundle(bundle) => { // if it is a share bundle we take either @@ -977,7 +977,7 @@ fn order_redistribution_address(order: &Order, protect_signers: &[Address]) -> O let txs = bundle.list_txs(); let (first_tx, _) = txs.first()?; - Some(first_tx.tx.signer()) + Some(first_tx.signer()) } Order::Tx(_) => { unreachable!("Mempool tx order can't have signer"); diff --git a/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs b/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs index f7d3bee0..ec6c95e6 100644 --- a/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs +++ b/crates/rbuilder/src/backtest/restore_landed_orders/find_landed_orders.rs @@ -36,7 +36,7 @@ impl SimplifiedOrder { } else { TxRevertBehavior::NotAllowed }; - (tx.tx.hash, revert) + (tx.hash(), revert) }) .collect(); SimplifiedOrder::new(id, vec![OrderChunk::new(txs, false, 0)]) diff --git a/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs b/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs index c95f6e69..051cbf70 100644 --- a/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs +++ b/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs @@ -11,18 +11,24 @@ use alloy_primitives::{Address, B256, I256}; use eyre::Context; use reth_chainspec::ChainSpec; use reth_db::DatabaseEnv; -use reth_primitives::{Receipt, TransactionSignedEcRecovered}; +use reth_primitives::{Receipt, TransactionSignedEcRecovered, TxHash}; use reth_provider::ProviderFactory; use std::sync::Arc; #[derive(Debug)] pub struct ExecutedTxs { - pub tx: TransactionSignedEcRecovered, + tx: TransactionSignedEcRecovered, pub receipt: Receipt, pub coinbase_profit: I256, pub conflicting_txs: Vec<(B256, Vec)>, } +impl ExecutedTxs { + pub fn hash(&self) -> TxHash { + self.tx.hash() + } +} + pub fn sim_historical_block( provider_factory: ProviderFactory>, chain_spec: Arc, @@ -98,7 +104,7 @@ pub fn sim_historical_block( }; results.push(ExecutedTxs { - tx: tx.tx, + tx: tx.into_internal_tx_unsecure(), receipt: result.receipt, coinbase_profit, conflicting_txs, @@ -115,7 +121,7 @@ fn find_suggested_fee_recipient( let coinbase = block.header.miner; let (last_tx_signer, last_tx_to) = if let Some((signer, to)) = txs .last() - .map(|tx| (tx.tx.signer(), tx.tx.to().unwrap_or_default())) + .map(|tx| (tx.signer(), tx.to().unwrap_or_default())) { (signer, to) } else { diff --git a/crates/rbuilder/src/bin/debug-bench-machine.rs b/crates/rbuilder/src/bin/debug-bench-machine.rs index 109aa8a0..4eeae1c6 100644 --- a/crates/rbuilder/src/bin/debug-bench-machine.rs +++ b/crates/rbuilder/src/bin/debug-bench-machine.rs @@ -89,11 +89,7 @@ async fn main() -> eyre::Result<()> { let tx = tx .try_ecrecovered() .ok_or_else(|| eyre::eyre!("Failed to recover tx"))?; - let tx = TransactionSignedEcRecoveredWithBlobs { - tx, - blobs_sidecar: Default::default(), - metadata: Default::default(), - }; + let tx = TransactionSignedEcRecoveredWithBlobs::new_for_testing(tx); let tx = MempoolTx::new(tx); Ok::<_, eyre::Error>(Order::Tx(tx)) }) diff --git a/crates/rbuilder/src/building/built_block_trace.rs b/crates/rbuilder/src/building/built_block_trace.rs index a68cf364..dabfe8b2 100644 --- a/crates/rbuilder/src/building/built_block_trace.rs +++ b/crates/rbuilder/src/building/built_block_trace.rs @@ -116,7 +116,6 @@ impl BuiltBlockTrace { &mut executed_tx_hashes_scratchpad }; for (tx, receipt) in res.txs.iter().zip(res.receipts.iter()) { - let tx = &tx.tx; executed_tx_hashes.push((tx.hash(), receipt.success)); if blocklist.contains(&tx.signer()) || tx.to().map(|to| blocklist.contains(&to)).unwrap_or(false) diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index 6d65a925..ff8adf32 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -376,7 +376,7 @@ impl ExecutionError { tx: tx_nonce, .. }), - )) => Some((order.list_txs().first()?.0.tx.signer(), *tx_nonce)), + )) => Some((order.list_txs().first()?.0.signer(), *tx_nonce)), ExecutionError::OrderError(OrderErr::Bundle(BundleErr::InvalidTransaction( hash, TransactionErr::InvalidTransaction(InvalidTransaction::NonceTooHigh { @@ -387,9 +387,8 @@ impl ExecutionError { let signer = order .list_txs() .iter() - .find(|(tx, _)| &tx.tx.hash == hash)? + .find(|(tx, _)| TransactionSignedEcRecoveredWithBlobs::hash(tx) == *hash)? .0 - .tx .signer(); Some((signer, *tx_nonce)) } @@ -629,11 +628,10 @@ impl PartialBlock { // double check blocked txs for tx_with_blob in &self.executed_tx { - let tx = &tx_with_blob.tx; - if ctx.blocklist.contains(&tx.signer()) { + if ctx.blocklist.contains(&tx_with_blob.signer()) { return Err(eyre::eyre!("To from blocked address.")); } - if let Some(to) = tx.to() { + if let Some(to) = tx_with_blob.to() { if ctx.blocklist.contains(&to) { return Err(eyre::eyre!("Tx to blocked address")); } @@ -681,7 +679,11 @@ impl PartialBlock { let block = Block { header, - body: self.executed_tx.into_iter().map(|t| t.tx.into()).collect(), + body: self + .executed_tx + .into_iter() + .map(|t| t.into_internal_tx_unsecure().into()) + .collect(), ommers: vec![], withdrawals, requests, diff --git a/crates/rbuilder/src/building/order_commit.rs b/crates/rbuilder/src/building/order_commit.rs index b779eb0a..59f43bda 100644 --- a/crates/rbuilder/src/building/order_commit.rs +++ b/crates/rbuilder/src/building/order_commit.rs @@ -396,7 +396,7 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { } let mut db = self.state.new_db_ref(); - let tx = &tx_with_blobs.tx; + let tx = &tx_with_blobs.internal_tx_unsecure(); if ctx.blocklist.contains(&tx.signer()) || tx .to() @@ -420,7 +420,7 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { } let mut tx_env = TxEnv::default(); - let tx_signed = tx_with_blobs.tx.clone().into_signed(); + let tx_signed = tx_with_blobs.internal_tx_unsecure().clone().into_signed(); tx_signed.fill_tx_env(&mut tx_env, tx_signed.recover_signer().unwrap()); let env = Env { @@ -557,7 +557,6 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { original_order_ids: Vec::new(), }; for tx_with_blobs in &bundle.txs { - let tx = &tx_with_blobs.tx; let result = self.commit_tx( tx_with_blobs, ctx, @@ -567,8 +566,10 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { )?; match result { Ok(res) => { - if !res.receipt.success && !bundle.reverting_tx_hashes.contains(&tx.hash()) { - return Ok(Err(BundleErr::TransactionReverted(tx.hash()))); + if !res.receipt.success + && !bundle.reverting_tx_hashes.contains(&tx_with_blobs.hash()) + { + return Ok(Err(BundleErr::TransactionReverted(tx_with_blobs.hash()))); } insert.gas_used += res.gas_used; @@ -581,10 +582,13 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { } Err(err) => { // if optional transaction, skip - if allow_tx_skip && bundle.reverting_tx_hashes.contains(&tx.hash()) { + if allow_tx_skip && bundle.reverting_tx_hashes.contains(&tx_with_blobs.hash()) { continue; } else { - return Ok(Err(BundleErr::InvalidTransaction(tx.hash(), err))); + return Ok(Err(BundleErr::InvalidTransaction( + tx_with_blobs.hash(), + err, + ))); } } } @@ -792,9 +796,7 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { if !res.receipt.success { match sbundle_tx.revert_behavior { crate::primitives::TxRevertBehavior::NotAllowed => { - return Ok(Err(BundleErr::TransactionReverted( - tx.tx.hash(), - ))); + return Ok(Err(BundleErr::TransactionReverted(tx.hash()))); } crate::primitives::TxRevertBehavior::AllowedIncluded => {} crate::primitives::TxRevertBehavior::AllowedExcluded => { @@ -828,7 +830,7 @@ impl<'a, 'b, Tracer: SimulationTracer> PartialBlockFork<'a, 'b, Tracer> { if allow_tx_skip && sbundle_tx.revert_behavior.can_revert() { continue; } else { - return Ok(Err(BundleErr::InvalidTransaction(tx.tx.hash(), err))); + return Ok(Err(BundleErr::InvalidTransaction(tx.hash(), err))); } } } diff --git a/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs b/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs index c30e60d3..264f449a 100644 --- a/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs +++ b/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs @@ -176,7 +176,7 @@ mod test { } .unwrap(); - assert_eq!(tx_with_blobs.tx.hash(), *pending_tx.tx_hash()); + assert_eq!(tx_with_blobs.hash(), *pending_tx.tx_hash()); assert_eq!(tx_with_blobs.blobs_sidecar.blobs.len(), 1); // send another tx without blobs @@ -198,7 +198,7 @@ mod test { } .unwrap(); - assert_eq!(tx_without_blobs.tx.hash(), *pending_tx.tx_hash()); + assert_eq!(tx_without_blobs.hash(), *pending_tx.tx_hash()); assert_eq!(tx_without_blobs.blobs_sidecar.blobs.len(), 0); } } diff --git a/crates/rbuilder/src/primitives/mod.rs b/crates/rbuilder/src/primitives/mod.rs index b88aab68..4486e0d0 100644 --- a/crates/rbuilder/src/primitives/mod.rs +++ b/crates/rbuilder/src/primitives/mod.rs @@ -395,12 +395,13 @@ impl ShareBundle { } } -/// First idea to handle blobs might change. +/// First idea to handle blobs, might change. /// Don't like the fact that blobs_sidecar exists no matter if TransactionSignedEcRecovered contains a non blob tx. +/// Great effort was put in avoiding simple access to the internal tx so we don't accidentally leak information on logs (particularly the tx sign). #[derive(Derivative)] -#[derivative(Debug, Clone, PartialEq, Eq)] +#[derivative(Clone, PartialEq, Eq)] pub struct TransactionSignedEcRecoveredWithBlobs { - pub tx: TransactionSignedEcRecovered, + tx: TransactionSignedEcRecovered, /// Will have a non empty BlobTransactionSidecar if TransactionSignedEcRecovered is 4844 pub blobs_sidecar: Arc, @@ -408,15 +409,20 @@ pub struct TransactionSignedEcRecoveredWithBlobs { pub metadata: Metadata, } -impl AsRef for TransactionSignedEcRecoveredWithBlobs { - fn as_ref(&self) -> &TransactionSignedEcRecovered { +impl AsRef for TransactionSignedEcRecoveredWithBlobs { + fn as_ref(&self) -> &TransactionSigned { &self.tx } } -impl AsRef for TransactionSignedEcRecoveredWithBlobs { - fn as_ref(&self) -> &TransactionSigned { - &self.tx +/// Custom fmt to avoid leaking information. +impl std::fmt::Debug for TransactionSignedEcRecoveredWithBlobs { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "TransactionSignedEcRecoveredWithBlobs {{ hash: {} }}", + self.hash(), + ) } } @@ -436,11 +442,16 @@ impl TransactionSignedEcRecoveredWithBlobs { if tx.transaction.blob_versioned_hashes().is_some() { return None; } - Some(Self { + Some(Self::new_for_testing(tx)) + } + + /// Creates a Self with empty blobs sidecar. No consistency check is performed, + pub fn new_for_testing(tx: TransactionSignedEcRecovered) -> Self { + Self { tx, - blobs_sidecar: Arc::new(BlobTransactionSidecar::default()), + blobs_sidecar: Default::default(), metadata: Default::default(), - }) + } } pub fn hash(&self) -> TxHash { @@ -451,8 +462,27 @@ impl TransactionSignedEcRecoveredWithBlobs { self.tx.signer() } + pub fn to(&self) -> Option
{ + self.tx.to() + } + + pub fn nonce(&self) -> u64 { + self.tx.nonce() + } + + /// USE CAREFULLY since this exposes the signed tx. + pub fn internal_tx_unsecure(&self) -> &TransactionSignedEcRecovered { + &self.tx + } + + /// USE CAREFULLY since this exposes the signed tx. + pub fn into_internal_tx_unsecure(self) -> TransactionSignedEcRecovered { + self.tx + } + /// Encodes the "raw" canonical format of transaction (NOT the one used in `eth_sendRawTransaction`) BLOB DATA IS NOT ENCODED. /// I intensionally omitted the version with blob data since we don't use it and may lead to confusions/bugs. + /// USE CAREFULLY since this exposes the signed tx. pub fn envelope_encoded_no_blobs(&self) -> Bytes { self.tx.envelope_encoded() } diff --git a/crates/rbuilder/src/utils/test_utils.rs b/crates/rbuilder/src/utils/test_utils.rs index 32f7941b..ab960b04 100644 --- a/crates/rbuilder/src/utils/test_utils.rs +++ b/crates/rbuilder/src/utils/test_utils.rs @@ -1,7 +1,6 @@ use crate::primitives::{OrderId, TransactionSignedEcRecoveredWithBlobs}; use alloy_primitives::{Address, B256, I256, U256}; use reth_primitives::{TransactionSigned, TransactionSignedEcRecovered}; -use std::sync::Arc; pub fn order_id(id: u64) -> OrderId { OrderId::Tx(hash(id)) @@ -24,8 +23,8 @@ pub fn i256(i: i64) -> I256 { } pub fn tx(tx_hash: u64) -> TransactionSignedEcRecoveredWithBlobs { - TransactionSignedEcRecoveredWithBlobs { - tx: TransactionSignedEcRecovered::from_signed_transaction( + TransactionSignedEcRecoveredWithBlobs::new_for_testing( + TransactionSignedEcRecovered::from_signed_transaction( TransactionSigned { hash: hash(tx_hash), signature: Default::default(), @@ -33,7 +32,5 @@ pub fn tx(tx_hash: u64) -> TransactionSignedEcRecoveredWithBlobs { }, Address::default(), ), - blobs_sidecar: Arc::new(Default::default()), - metadata: Default::default(), - } + ) } From 240ce56daf72e338adf180fdba154b697576d5e6 Mon Sep 17 00:00:00 2001 From: liamaharon Date: Mon, 9 Sep 2024 04:20:55 +1000 Subject: [PATCH 03/30] Improve metrics developer experience (#170) Currently, to add a new metric code needs to be modified in two places: 1. The big lazy_static declaring metrics 2. Inside `fn register_custom_metrics` to register it This PR adds a macro `register_metrics` we can use in place of `lazy_static` when declaring metrics, which handles registering the declared metrics and therefore removing the requirement for `fn register_custom_metrics` entirely. Metrics are eagerly initialised with `ctor` so they will show up in the Prometheus metrics endpoint immediately. I decided on this approach rather than switch to an entirely different framework like what reth uses so it would slot into the existing pattern with minimal changes. # Usage ```rust register_metrics! { pub static CURRENT_BLOCK: IntGauge = IntGauge::new("current_block", "Current Block").unwrap(); pub static BLOCK_FILL_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("block_fill_time", "Block Fill Times (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), &["builder_name"] ) .unwrap(); } ``` expands to ```rust lazy_static! { pub static ref CURRENT_BLOCK: IntGauge = { let metric = IntGauge::new("current_block", "Current Block").unwrap(); REGISTRY.register(Box::new(metric.clone())).unwrap(); metric }; pub static ref BLOCK_FILL_TIME: HistogramVec = { let metric = HistogramVec::new( HistogramOpts::new("block_fill_time", "Block Fill Times (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), &["builder_name"] ).unwrap(); REGISTRY.register(Box::new(metric.clone())).unwrap(); metric }; } #[ctor] fn initialize_metrics() { let _ = *CURRENT_BLOCK; let _ = *BLOCK_FILL_TIME; } --- Cargo.lock | 21 +++ Cargo.toml | 3 +- crates/rbuilder/Cargo.toml | 2 + crates/rbuilder/src/telemetry/metrics.rs | 153 +++++------------- .../src/telemetry/metrics_macros/Cargo.toml | 12 ++ .../src/telemetry/metrics_macros/src/lib.rs | 107 ++++++++++++ crates/rbuilder/src/telemetry/mod.rs | 2 - 7 files changed, 181 insertions(+), 119 deletions(-) create mode 100644 crates/rbuilder/src/telemetry/metrics_macros/Cargo.toml create mode 100644 crates/rbuilder/src/telemetry/metrics_macros/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 6cb5d49c..fa70d501 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2562,6 +2562,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote", + "syn 2.0.72", +] + [[package]] name = "ctr" version = "0.7.0" @@ -5805,6 +5815,15 @@ dependencies = [ "sketches-ddsketch", ] +[[package]] +name = "metrics_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "mev-share-sse" version = "0.1.6" @@ -7605,6 +7624,7 @@ dependencies = [ "criterion", "crossbeam-queue", "csv", + "ctor", "derivative", "ethereum-consensus", "ethereum_ssz", @@ -7624,6 +7644,7 @@ dependencies = [ "lru", "lz4_flex", "mempool-dumpster", + "metrics_macros", "mev-share-sse", "mockall", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 41f711ab..d5d773ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] members = [ "crates/rbuilder", - "crates/rbuilder/src/test_utils" + "crates/rbuilder/src/test_utils", + "crates/rbuilder/src/telemetry/metrics_macros" ] resolver = "2" diff --git a/crates/rbuilder/Cargo.toml b/crates/rbuilder/Cargo.toml index 822719f0..c98276df 100644 --- a/crates/rbuilder/Cargo.toml +++ b/crates/rbuilder/Cargo.toml @@ -55,6 +55,7 @@ ethereum_ssz_derive.workspace = true ethereum_ssz.workspace = true test_utils = { path = "src/test_utils" } +metrics_macros = { path = "src/telemetry/metrics_macros" } reqwest = { version = "0.11.20", features = ["blocking"] } serde_with = { version = "3.8.1", features = ["time_0_3"] } @@ -102,6 +103,7 @@ prometheus = "0.13.4" hyper = { version = "1.3.1", features = ["server", "full"] } warp = "0.3.7" lazy_static = "1.4.0" +ctor = "0.2" toml = "0.8.8" ahash = "0.8.6" rand = "0.8.5" diff --git a/crates/rbuilder/src/telemetry/metrics.rs b/crates/rbuilder/src/telemetry/metrics.rs index 023b9907..f51991d1 100644 --- a/crates/rbuilder/src/telemetry/metrics.rs +++ b/crates/rbuilder/src/telemetry/metrics.rs @@ -10,7 +10,9 @@ use crate::{ }; use alloy_primitives::{utils::Unit, U256}; use bigdecimal::num_traits::Pow; +use ctor::ctor; use lazy_static::lazy_static; +use metrics_macros::register_metrics; use prometheus::{ Counter, HistogramOpts, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry, @@ -33,37 +35,40 @@ const BLOCK_METRICS_TIMESTAMP_UPPER_DELTA: time::Duration = time::Duration::seco lazy_static! { pub static ref REGISTRY: Registry = Registry::new(); - pub static ref BLOCK_FILL_TIME: HistogramVec = HistogramVec::new( +} + +register_metrics! { + pub static BLOCK_FILL_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("block_fill_time", "Block Fill Times (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), &["builder_name"] ) .unwrap(); - pub static ref BLOCK_FINALIZE_TIME: HistogramVec = HistogramVec::new( + pub static BLOCK_FINALIZE_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("block_finalize_time", "Block Finalize Times (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), &["builder_name"] ) .unwrap(); - pub static ref BLOCK_BUILT_TXS: HistogramVec = HistogramVec::new( + pub static BLOCK_BUILT_TXS: HistogramVec = HistogramVec::new( HistogramOpts::new("block_built_txs", "Transactions in the built block") .buckets(linear_buckets_range(1.0, 1000.0, 100)), &["builder_name"] ) .unwrap(); - pub static ref BLOCK_BUILT_BLOBS: HistogramVec = HistogramVec::new( + pub static BLOCK_BUILT_BLOBS: HistogramVec = HistogramVec::new( HistogramOpts::new("block_built_blobs", "Blobs in the built block") .buckets(linear_buckets_range(1.0, 32.0, 100)), &["builder_name"] ) .unwrap(); - pub static ref BLOCK_BUILT_GAS_USED: HistogramVec = HistogramVec::new( + pub static BLOCK_BUILT_GAS_USED: HistogramVec = HistogramVec::new( HistogramOpts::new("block_built_gas_used", "Gas used in the built block") .buckets(exponential_buckets_range(21_000.0, 30_000_000.0, 100)), &["builder_name"] ) .unwrap(); - pub static ref BLOCK_BUILT_SIM_GAS_USED: HistogramVec = HistogramVec::new( + pub static BLOCK_BUILT_SIM_GAS_USED: HistogramVec = HistogramVec::new( HistogramOpts::new( "block_built_sim_gas_used", "Gas used in the built block including failing bundles" @@ -72,7 +77,7 @@ lazy_static! { &["builder_name"] ) .unwrap(); - pub static ref BLOCK_BUILT_MGAS_PER_SECOND: HistogramVec = HistogramVec::new( + pub static BLOCK_BUILT_MGAS_PER_SECOND: HistogramVec = HistogramVec::new( HistogramOpts::new( "block_built_mgas_per_second", "MGas/s for the built block (including failing txs)" @@ -81,42 +86,42 @@ lazy_static! { &["builder_name"] ) .unwrap(); - pub static ref BLOCK_VALIDATION_TIME: HistogramVec = HistogramVec::new( + pub static BLOCK_VALIDATION_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("block_validation_time", "Block Validation Times (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), &["builder_name"] ) .unwrap(); - pub static ref CURRENT_BLOCK: IntGauge = + pub static CURRENT_BLOCK: IntGauge = IntGauge::new("current_block", "Current Block").unwrap(); - pub static ref ORDERPOOL_TXS: IntGauge = + pub static ORDERPOOL_TXS: IntGauge = IntGauge::new("orderpool_txs", "Transactions In The Orderpool").unwrap(); - pub static ref ORDERPOOL_BUNDLES: IntGauge = + pub static ORDERPOOL_BUNDLES: IntGauge = IntGauge::new("orderpool_bundles", "Bundles In The Orderpool").unwrap(); - pub static ref RELAY_ERRORS: IntCounterVec = IntCounterVec::new( + pub static RELAY_ERRORS: IntCounterVec = IntCounterVec::new( Opts::new("relay_errors", "counter of relay errors"), &["relay", "kind"] ) .unwrap(); - pub static ref BLOCK_SIM_ERRORS: IntCounterVec = IntCounterVec::new( + pub static BLOCK_SIM_ERRORS: IntCounterVec = IntCounterVec::new( Opts::new("block_sim_errors", "counter of block simulation errors"), &[] ) .unwrap(); - pub static ref BLOCK_API_ERRORS: IntCounterVec = IntCounterVec::new( + pub static BLOCK_API_ERRORS: IntCounterVec = IntCounterVec::new( Opts::new("block_api_errors", "counter of the block processor errors"), &[] ) .unwrap(); - pub static ref SIMULATED_OK_ORDERS: IntCounter = + pub static SIMULATED_OK_ORDERS: IntCounter = IntCounter::new("simulated_ok_orders", "Simulated succeeded orders").unwrap(); - pub static ref SIMULATED_FAILED_ORDERS: IntCounter = + pub static SIMULATED_FAILED_ORDERS: IntCounter = IntCounter::new("simulated_failed_orders", "Simulated failed orders").unwrap(); - pub static ref SIMULATION_GAS_USED: IntCounter = + pub static SIMULATION_GAS_USED: IntCounter = IntCounter::new("simulation_gas_used", "Simulation gas used").unwrap(); - pub static ref ACTIVE_SLOTS: IntCounter = + pub static ACTIVE_SLOTS: IntCounter = IntCounter::new("active_slots", "Slots when builder was active").unwrap(); - pub static ref INITIATED_SUBMISSIONS: IntCounterVec = IntCounterVec::new( + pub static INITIATED_SUBMISSIONS: IntCounterVec = IntCounterVec::new( Opts::new( "initiated_submissions", "Number of initiated submissions to the relays" @@ -124,18 +129,18 @@ lazy_static! { &["optimistic"], ) .unwrap(); - pub static ref RELAY_SUBMIT_TIME: HistogramVec = HistogramVec::new( + pub static RELAY_SUBMIT_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("relay_submit_time", "Time to send bid to the relay (ms)") .buckets(linear_buckets_range(0.0, 3000.0, 50)), &["relay"], ) .unwrap(); - pub static ref VERSION: IntGaugeVec = IntGaugeVec::new( + pub static VERSION: IntGaugeVec = IntGaugeVec::new( Opts::new("version", "Version of the builder"), &["git", "git_ref", "build_time_utc"] ) .unwrap(); - pub static ref RELAY_ACCEPTED_SUBMISSIONS: IntCounterVec = IntCounterVec::new( + pub static RELAY_ACCEPTED_SUBMISSIONS: IntCounterVec = IntCounterVec::new( Opts::new( "relay_accepted_submissions", "Number of accepted submissions" @@ -143,7 +148,7 @@ lazy_static! { &["relay", "optimistic"] ) .unwrap(); - pub static ref SIMULATION_THREAD_WORK_TIME: IntCounterVec = IntCounterVec::new( + pub static SIMULATION_THREAD_WORK_TIME: IntCounterVec = IntCounterVec::new( Opts::new( "simulation_thread_work_time", "Time spent working in simulation thread (mus)" @@ -151,7 +156,7 @@ lazy_static! { &["worker_id"] ) .unwrap(); - pub static ref SIMULATION_THREAD_WAIT_TIME: IntCounterVec = IntCounterVec::new( + pub static SIMULATION_THREAD_WAIT_TIME: IntCounterVec = IntCounterVec::new( Opts::new( "simulation_thread_wait_time", "Time spent waiting for input in simulation thread (mus)" @@ -159,7 +164,7 @@ lazy_static! { &["worker_id"] ) .unwrap(); - pub static ref ORDERS_IN_LAST_BUILT_BLOCK_E2E_LAT_MS: HistogramVec = HistogramVec::new( + pub static ORDERS_IN_LAST_BUILT_BLOCK_E2E_LAT_MS: HistogramVec = HistogramVec::new( HistogramOpts::new( "orders_in_last_built_block_e2e_lat", "For all blocks that are ready for submission to the relay its = min over orders (submission start - order received)" @@ -169,16 +174,16 @@ lazy_static! { ) .unwrap(); - pub static ref PROVIDER_REOPEN_COUNTER: IntCounter = IntCounter::new( + pub static PROVIDER_REOPEN_COUNTER: IntCounter = IntCounter::new( "provider_reopen_counter", "Counter of provider reopens").unwrap(); - pub static ref PROVIDER_BAD_REOPEN_COUNTER: IntCounter = IntCounter::new( + pub static PROVIDER_BAD_REOPEN_COUNTER: IntCounter = IntCounter::new( "provider_bad_reopen_counter", "Counter of provider reopens").unwrap(); - pub static ref TXFETCHER_TRANSACTION_COUNTER: IntCounter = IntCounter::new( + pub static TXFETCHER_TRANSACTION_COUNTER: IntCounter = IntCounter::new( "txfetcher_transaction_counter", "Counter of transactions fetched by txfetcher service").unwrap(); - pub static ref TXFETCHER_TRANSACTION_QUERY_TIME: HistogramVec = HistogramVec::new( + pub static TXFETCHER_TRANSACTION_QUERY_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("txfetcher_transaction_query_time", "Time to retrieve a transaction from the txpool (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), &[], @@ -189,7 +194,7 @@ lazy_static! { ///////////////////////////////// /// We decide this at the end of the submission to relays - pub static ref SUBSIDIZED_BLOCK_COUNT: IntCounterVec = IntCounterVec::new( + pub static SUBSIDIZED_BLOCK_COUNT: IntCounterVec = IntCounterVec::new( Opts::new( "subsidized_block_count", "Subsidized block count" @@ -200,14 +205,14 @@ lazy_static! { /// We decide this at the end of the submission to relays /// We expect to see values around .001 /// We only count subsidized blocks. - pub static ref SUBSIDY_VALUE: HistogramVec = HistogramVec::new( + pub static SUBSIDY_VALUE: HistogramVec = HistogramVec::new( HistogramOpts::new("subsidy_value", "Subsidy value") .buckets(exponential_buckets_range(0.0001, 0.05, 1000)), &["kind"], ) .unwrap(); - pub static ref TOTAL_LANDED_SUBSIDIES_SUM: Counter = + pub static TOTAL_LANDED_SUBSIDIES_SUM: Counter = Counter::new("total_landed_subsidies_sum", "Sum of all total landed subsidies").unwrap(); } @@ -419,90 +424,6 @@ pub fn add_subsidy_value(value: U256, landed: bool) { } } -pub(super) fn register_custom_metrics() { - REGISTRY - .register(Box::new(BLOCK_FILL_TIME.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_FINALIZE_TIME.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_VALIDATION_TIME.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_BUILT_TXS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_BUILT_GAS_USED.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_BUILT_SIM_GAS_USED.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_BUILT_MGAS_PER_SECOND.clone())) - .unwrap(); - REGISTRY.register(Box::new(CURRENT_BLOCK.clone())).unwrap(); - REGISTRY.register(Box::new(ORDERPOOL_TXS.clone())).unwrap(); - REGISTRY - .register(Box::new(ORDERPOOL_BUNDLES.clone())) - .unwrap(); - REGISTRY.register(Box::new(RELAY_ERRORS.clone())).unwrap(); - REGISTRY - .register(Box::new(BLOCK_SIM_ERRORS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(BLOCK_API_ERRORS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(SIMULATED_FAILED_ORDERS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(SIMULATED_OK_ORDERS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(SIMULATION_GAS_USED.clone())) - .unwrap(); - REGISTRY.register(Box::new(ACTIVE_SLOTS.clone())).unwrap(); - REGISTRY - .register(Box::new(INITIATED_SUBMISSIONS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(RELAY_SUBMIT_TIME.clone())) - .unwrap(); - REGISTRY.register(Box::new(VERSION.clone())).unwrap(); - REGISTRY - .register(Box::new(RELAY_ACCEPTED_SUBMISSIONS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(SIMULATION_THREAD_WORK_TIME.clone())) - .unwrap(); - REGISTRY - .register(Box::new(SIMULATION_THREAD_WAIT_TIME.clone())) - .unwrap(); - REGISTRY - .register(Box::new(ORDERS_IN_LAST_BUILT_BLOCK_E2E_LAT_MS.clone())) - .unwrap(); - REGISTRY - .register(Box::new(SUBSIDIZED_BLOCK_COUNT.clone())) - .unwrap(); - REGISTRY.register(Box::new(SUBSIDY_VALUE.clone())).unwrap(); - REGISTRY - .register(Box::new(TOTAL_LANDED_SUBSIDIES_SUM.clone())) - .unwrap(); - REGISTRY - .register(Box::new(PROVIDER_REOPEN_COUNTER.clone())) - .unwrap(); - REGISTRY - .register(Box::new(PROVIDER_BAD_REOPEN_COUNTER.clone())) - .unwrap(); - REGISTRY - .register(Box::new(TXFETCHER_TRANSACTION_COUNTER.clone())) - .unwrap(); - REGISTRY - .register(Box::new(TXFETCHER_TRANSACTION_QUERY_TIME.clone())) - .unwrap(); -} - pub(super) fn gather_prometheus_metrics() -> String { use prometheus::Encoder; let encoder = prometheus::TextEncoder::new(); diff --git a/crates/rbuilder/src/telemetry/metrics_macros/Cargo.toml b/crates/rbuilder/src/telemetry/metrics_macros/Cargo.toml new file mode 100644 index 00000000..7b44a546 --- /dev/null +++ b/crates/rbuilder/src/telemetry/metrics_macros/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "metrics_macros" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["full"] } diff --git a/crates/rbuilder/src/telemetry/metrics_macros/src/lib.rs b/crates/rbuilder/src/telemetry/metrics_macros/src/lib.rs new file mode 100644 index 00000000..ca3d13c4 --- /dev/null +++ b/crates/rbuilder/src/telemetry/metrics_macros/src/lib.rs @@ -0,0 +1,107 @@ +extern crate proc_macro; +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, Item}; + +/// Generates and registers the given static Prometheus metrics to a static +/// Registry named REGISTRY. +/// +/// This avoids the need for the caller to manually initialize the registry +/// and call REGISTERY.register on every metric. +/// +/// Metrics are eagerly initialized when the program starts with `ctor`, +/// so they will show up in the Prometheus metrics endpoint immediately. +/// +/// Note: `lazy_static::lazy_static` and `ctor::ctor` must be in scope. +/// +/// # Example +/// +/// ```ignore +/// register_metrics! { +/// pub static CURRENT_BLOCK: IntGauge = IntGauge::new("current_block", "Current Block").unwrap(); +/// +/// pub static BLOCK_FILL_TIME: HistogramVec = HistogramVec::new( +/// HistogramOpts::new("block_fill_time", "Block Fill Times (ms)") +/// .buckets(exponential_buckets_range(1.0, 3000.0, 100)), +/// &["builder_name"] +/// ) +/// .unwrap(); +/// } +/// ``` +/// +/// expands to +/// +/// ```ignore +/// lazy_static! { +/// pub static ref CURRENT_BLOCK: IntGauge = { +/// let metric = IntGauge::new("current_block", "Current Block").unwrap(); +/// REGISTRY.register(Box::new(metric.clone())).unwrap(); +/// metric +/// }; +/// +/// pub static ref BLOCK_FILL_TIME: HistogramVec = { +/// let metric = HistogramVec::new( +/// HistogramOpts::new("block_fill_time", "Block Fill Times (ms)") +/// .buckets(exponential_buckets_range(1.0, 3000.0, 100)), +/// &["builder_name"] +/// ).unwrap(); +/// REGISTRY.register(Box::new(metric.clone())).expect("Failed to register metric"); +/// metric +/// }; +/// } +/// +/// #[ctor] +/// fn initialize_metrics() { +/// // Force initialization of lazy statics +/// let _ = *CURRENT_BLOCK; +/// let _ = *BLOCK_FILL_TIME; +/// } +/// ``` +#[proc_macro] +pub fn register_metrics(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as syn::File); + + // Stuff to put in lazy_static! + let mut metrics = quote! {}; + + // Stuff to put in ctor + let mut initializers = quote! {}; + + for item in input.items { + if let Item::Static(static_item) = item { + let vis = &static_item.vis; + let ident = &static_item.ident; + let ty = &static_item.ty; + let expr = &static_item.expr; + + // Create the static metric call REGISTER.register with it. + metrics.extend(quote! { + #vis static ref #ident: #ty = { + let metric = #expr; + REGISTRY.register(Box::new(metric.clone())).expect("Failed to register metric"); + metric + }; + }); + + // Make sure the metric is eagerly initialized + initializers.extend(quote! { + let _ = *#ident; + }); + } else { + panic!("register_metrics! only supports static items"); + } + } + + let out = quote! { + lazy_static! { + #metrics + } + + #[ctor] + fn initialize_metrics() { + #initializers + } + }; + + TokenStream::from(out) +} diff --git a/crates/rbuilder/src/telemetry/mod.rs b/crates/rbuilder/src/telemetry/mod.rs index ea64b4df..179e449f 100644 --- a/crates/rbuilder/src/telemetry/mod.rs +++ b/crates/rbuilder/src/telemetry/mod.rs @@ -55,8 +55,6 @@ async fn reset_log_handle() -> Result { } pub async fn spawn_telemetry_server(addr: SocketAddr, version: Version) -> eyre::Result<()> { - register_custom_metrics(); - set_version(version); // metrics over /debug/metrics/prometheus From 367ccc986d3b55117a06c485ad03d30cb9097529 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:02:03 -0300 Subject: [PATCH 04/30] store_error feature optional. (#168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This PR allows to optionally disable the store_error feature since it allows storing arbitrary data for further analysis. Sometimes it's even used to store fully sealed blocks. ## 💡 Motivation and Context This change is needed to avoid data leaks in a TEE context. ## ✅ I have completed the following steps: * [X ] Run `make lint` * [X] Run `make test` * [ ] Added tests (if applicable) --- crates/rbuilder/src/bin/dummy-builder.rs | 6 +- .../rbuilder/src/live_builder/base_config.rs | 5 +- crates/rbuilder/src/live_builder/mod.rs | 10 ++- crates/rbuilder/src/utils/error_storage.rs | 87 +++++++++++-------- 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/crates/rbuilder/src/bin/dummy-builder.rs b/crates/rbuilder/src/bin/dummy-builder.rs index 71cd5f6c..f8384946 100644 --- a/crates/rbuilder/src/bin/dummy-builder.rs +++ b/crates/rbuilder/src/bin/dummy-builder.rs @@ -18,8 +18,8 @@ use rbuilder::{ }, live_builder::{ base_config::{ - DEFAULT_EL_NODE_IPC_PATH, DEFAULT_ERROR_STORAGE_PATH, DEFAULT_INCOMING_BUNDLES_PORT, - DEFAULT_IP, DEFAULT_RETH_DB_PATH, + DEFAULT_EL_NODE_IPC_PATH, DEFAULT_INCOMING_BUNDLES_PORT, DEFAULT_IP, + DEFAULT_RETH_DB_PATH, }, config::create_provider_factory, order_input::{ @@ -72,7 +72,7 @@ async fn main() -> eyre::Result<()> { let builder = LiveBuilder::, MevBoostSlotDataGenerator> { watchdog_timeout: Duration::from_secs(10000), - error_storage_path: DEFAULT_ERROR_STORAGE_PATH.parse().unwrap(), + error_storage_path: None, simulation_threads: 1, blocks_source: payload_event, order_input_config: OrderInputConfig::new( diff --git a/crates/rbuilder/src/live_builder/base_config.rs b/crates/rbuilder/src/live_builder/base_config.rs index 52711831..40d4081f 100644 --- a/crates/rbuilder/src/live_builder/base_config.rs +++ b/crates/rbuilder/src/live_builder/base_config.rs @@ -49,7 +49,7 @@ pub struct BaseConfig { log_level: EnvOrValue, pub log_color: bool, - pub error_storage_path: PathBuf, + pub error_storage_path: Option, coinbase_secret_key: EnvOrValue, @@ -358,7 +358,6 @@ where } } -pub const DEFAULT_ERROR_STORAGE_PATH: &str = "/tmp/rbuilder-error.sqlite"; pub const DEFAULT_CL_NODE_URL: &str = "http://127.0.0.1:3500"; pub const DEFAULT_EL_NODE_IPC_PATH: &str = "/tmp/reth.ipc"; pub const DEFAULT_INCOMING_BUNDLES_PORT: u16 = 8645; @@ -372,7 +371,7 @@ impl Default for BaseConfig { log_json: false, log_level: "info".into(), log_color: false, - error_storage_path: DEFAULT_ERROR_STORAGE_PATH.parse().unwrap(), + error_storage_path: None, coinbase_secret_key: "".into(), flashbots_db: None, el_node_ipc_path: "/tmp/reth.ipc".parse().unwrap(), diff --git a/crates/rbuilder/src/live_builder/mod.rs b/crates/rbuilder/src/live_builder/mod.rs index 2f3fae4c..aa6a5da6 100644 --- a/crates/rbuilder/src/live_builder/mod.rs +++ b/crates/rbuilder/src/live_builder/mod.rs @@ -59,7 +59,7 @@ pub trait SlotSource { #[derive(Debug)] pub struct LiveBuilder { pub watchdog_timeout: Duration, - pub error_storage_path: PathBuf, + pub error_storage_path: Option, pub simulation_threads: usize, pub order_input_config: OrderInputConfig, pub blocks_source: BlocksSourceType, @@ -96,9 +96,11 @@ impl self.coinbase_signer.address ); - spawn_error_storage_writer(self.error_storage_path, self.global_cancellation.clone()) - .await - .with_context(|| "Error spawning error storage writer")?; + if let Some(error_storage_path) = self.error_storage_path { + spawn_error_storage_writer(error_storage_path, self.global_cancellation.clone()) + .await + .with_context(|| "Error spawning error storage writer")?; + } let mut inner_jobs_handles = Vec::new(); let mut payload_events_channel = self.blocks_source.recv_slot_channel(); diff --git a/crates/rbuilder/src/utils/error_storage.rs b/crates/rbuilder/src/utils/error_storage.rs index 96f2f965..25bf8d79 100644 --- a/crates/rbuilder/src/utils/error_storage.rs +++ b/crates/rbuilder/src/utils/error_storage.rs @@ -5,7 +5,11 @@ use crossbeam_queue::ArrayQueue; use lazy_static::lazy_static; use sqlx::{sqlite::SqliteConnectOptions, ConnectOptions, Executor, SqliteConnection}; -use std::{path::Path, time::Duration}; +use std::{ + path::Path, + sync::{Arc, Mutex}, + time::Duration, +}; use tokio_util::sync::CancellationToken; use tracing::{error, info_span, warn}; @@ -16,6 +20,9 @@ const MAX_ERRORS_PER_CATEGORY: usize = 100; // Maximum size of the payload in bytes (100 mb) const MAX_PAYLOAD_SIZE_BYTES: usize = 100_000_000; +// If events don't get processed fst enough we drop them. +const MAX_PENDING_EVENTS: usize = 500; + #[derive(Debug)] struct ErrorEvent { category: String, @@ -24,7 +31,12 @@ struct ErrorEvent { } lazy_static! { - static ref EVENT_QUEUE: ArrayQueue = ArrayQueue::new(500); + /// Not using null object pattern due to some generic on trait problems. + static ref EVENT_QUEUE: Mutex>>> = Mutex::new(None); +} + +fn event_queue() -> Option>> { + EVENT_QUEUE.lock().unwrap().clone() } /// Spawn a new error storage writer. @@ -34,18 +46,23 @@ pub async fn spawn_error_storage_writer( global_cancel: CancellationToken, ) -> eyre::Result<()> { let mut storage = ErrorEventStorage::new_from_path(db_path).await?; - + *EVENT_QUEUE.lock().unwrap() = Some(Arc::new(ArrayQueue::new(MAX_PENDING_EVENTS))); tokio::spawn(async move { while !global_cancel.is_cancelled() { - if let Some(event) = EVENT_QUEUE.pop() { - if let Err(err) = storage.write_error_event(&event).await { - warn!( - category = event.category, - "Error writing error event to storage: {:?}", err - ); + if let Some(event_queue) = event_queue() { + if let Some(event) = event_queue.pop() { + if let Err(err) = storage.write_error_event(&event).await { + warn!( + category = event.category, + "Error writing error event to storage: {:?}", err + ); + } + } else { + tokio::time::sleep(Duration::from_millis(100)).await; } } else { - tokio::time::sleep(Duration::from_millis(100)).await; + error!("error_storage writing task has no event queue"); + return; } } }); @@ -58,32 +75,34 @@ pub async fn spawn_error_storage_writer( /// `error` is a string that describes the error /// `payload` is a serializable payload that will be stored with the error as a json pub fn store_error_event(category: &str, error: &str, payload: T) { - let span = info_span!("store_error_event", category, error); - let _span_guard = span.enter(); - - let payload_json = match serde_json::to_string(&payload) { - Ok(res) => res, - Err(err) => { - error!("Error serializing error payload: {:?}", err); + if let Some(event_queue) = event_queue() { + let span = info_span!("store_error_event", category, error); + let _span_guard = span.enter(); + + let payload_json = match serde_json::to_string(&payload) { + Ok(res) => res, + Err(err) => { + error!("Error serializing error payload: {:?}", err); + return; + } + }; + if payload_json.as_bytes().len() > MAX_PAYLOAD_SIZE_BYTES { + error!( + "Error payload is too large, not storing error event. Payload size: {}", + payload_json.as_bytes().len() + ); return; } - }; - if payload_json.as_bytes().len() > MAX_PAYLOAD_SIZE_BYTES { - error!( - "Error payload is too large, not storing error event. Payload size: {}", - payload_json.as_bytes().len() - ); - return; - } - if EVENT_QUEUE - .push(ErrorEvent { - category: category.to_string(), - error: error.to_string(), - payload: payload_json, - }) - .is_err() - { - error!("Error storing error event, queue is full."); + if event_queue + .push(ErrorEvent { + category: category.to_string(), + error: error.to_string(), + payload: payload_json, + }) + .is_err() + { + error!("Error storing error event, queue is full."); + } } } From 189fc142832f246d7b6e7ae78ca7675a1caac210 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Mon, 9 Sep 2024 15:08:24 +0100 Subject: [PATCH 05/30] Use root playgroung config toml file (#173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This PR uses the root playground config TOML file for the playground integration tests instead of creating one ad-hoc for the test. It had to be like that before because `rbuilder` could not expand $HOME in the config file, but, that was resolved in #114. --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [] Added tests (if applicable) --- .github/workflows/checks.yaml | 12 +-- crates/rbuilder/src/integration/playground.rs | 77 ++----------------- crates/rbuilder/src/integration/simple.rs | 2 +- 3 files changed, 13 insertions(+), 78 deletions(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index b1154c9f..d4bd932e 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -95,23 +95,25 @@ jobs: run: cargo build - name: Run the playground - run: builder-playground --output /tmp/playground & + run: builder-playground & - name: Run integration tests run: cargo test --package rbuilder --lib -- integration env: - PLAYGROUND_DIR: /tmp/playground + PLAYGROUND: TRUE - - name: Move test integration logs to playground logs to archive + - name: Aggregate playground logs # This steps fails if the test fails early and the playground logs dir has not been created if: ${{ failure() }} run: | - mv integration_logs /tmp/playground/logs + mkdir /tmp/playground-logs + mv $HOME/.playground/devnet/logs /tmp/playground-logs + mv integration_logs /tmp/playground-logs - name: Archive playground logs uses: actions/upload-artifact@v4 if: ${{ failure() }} with: name: playground-logs - path: /tmp/playground/logs + path: /tmp/playground-logs retention-days: 5 diff --git a/crates/rbuilder/src/integration/playground.rs b/crates/rbuilder/src/integration/playground.rs index 6508dacf..7d26374b 100644 --- a/crates/rbuilder/src/integration/playground.rs +++ b/crates/rbuilder/src/integration/playground.rs @@ -43,31 +43,14 @@ fn open_log_file(path: PathBuf) -> io::Result { impl Playground { pub fn new() -> Result { - // TODO: Fix unwraps - let playground_dir = std::env::var("PLAYGROUND_DIR") - .map_err(|_| PlaygroundError::IntegrationPathNotFound)?; - - // append to the config template the paths to the playground - let mut config = CONFIG_TEMPLATE.to_string(); - config.insert_str( - 0, - format!("chain = \"{}/genesis.json\"\n", playground_dir).as_str(), - ); - config.insert_str( - 0, - format!("reth_datadir = \"{}/data_reth\"\n", playground_dir).as_str(), - ); - - // write the config into /tmp/rbuilder.toml - let mut file = - File::create("/tmp/rbuilder.toml").map_err(|_| PlaygroundError::SetupError)?; - file.write_all(config.as_bytes()) - .map_err(|_| PlaygroundError::SetupError)?; - // load the binary from the cargo_dir let mut bin_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); bin_path.push("../../target/debug/rbuilder"); + // Use the config file from the root directory + let config_path = + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../config-playground.toml"); + let dt: OffsetDateTime = SystemTime::now().into(); let format = format_description::parse("[year]_[month]_[day]_[hour]_[minute]_[second]") @@ -85,7 +68,7 @@ impl Playground { let mut cmd = Command::new(bin_path.clone()); - cmd.arg("run").arg("/tmp/rbuilder.toml"); + cmd.arg("run").arg(config_path); cmd.stdout(stdout).stderr(stderr); let builder = match cmd.spawn() { @@ -193,53 +176,3 @@ impl Drop for Playground { .expect("could not kill mev-boost-server"); } } - -const CONFIG_TEMPLATE: &str = r#" -log_json = false -log_level = "info,rbuilder=debug" -telemetry_port = 6060 -telemetry_ip = "0.0.0.0" - -relay_secret_key = "5eae315483f028b5cdd5d1090ff0c7618b18737ea9bf3c35047189db22835c48" -coinbase_secret_key = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" - -cl_node_url = ["http://localhost:3500"] -jsonrpc_server_port = 8645 -jsonrpc_server_ip = "0.0.0.0" -el_node_ipc_path = "/tmp/reth.ipc" -extra_data = "⚡🤖" - -dry_run = false -dry_run_validation_url = "http://localhost:8545" - -blocks_processor_url = "http://block_processor.internal" -ignore_cancellable_orders = true - -sbundle_mergeabe_signers = [] -# slot_delta_to_start_submits_ms is usually negative since we start bidding BEFORE the slot start -#slot_delta_to_start_submits_ms = -5000 -live_builders = ["mp-ordering"] - -[[relays]] -name = "custom" -url = "http://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@localhost:5555" -priority = 0 -use_ssz_for_submit = false -use_gzip_for_submit = false - -[[builders]] -name = "mgp-ordering" -algo = "ordering-builder" -discard_txs = true -sorting = "mev-gas-price" -failed_order_retries = 1 -drop_failed_orders = true - -[[builders]] -name = "mp-ordering" -algo = "ordering-builder" -discard_txs = true -sorting = "max-profit" -failed_order_retries = 1 -drop_failed_orders = true -"#; diff --git a/crates/rbuilder/src/integration/simple.rs b/crates/rbuilder/src/integration/simple.rs index e66f1681..17e28492 100644 --- a/crates/rbuilder/src/integration/simple.rs +++ b/crates/rbuilder/src/integration/simple.rs @@ -10,7 +10,7 @@ mod tests { use test_utils::ignore_if_env_not_set; use url::Url; - #[ignore_if_env_not_set("PLAYGROUND_DIR")] // TODO: Change with a custom macro (i.e ignore_if_not_playground) + #[ignore_if_env_not_set("PLAYGROUND")] // TODO: Change with a custom macro (i.e ignore_if_not_playground) #[tokio::test] async fn test_simple_example() { // This test sends a transaction ONLY to the builder and waits for the block to be built with it. From ccf4677ba3aa8cc1b50e14b6bda4947322ee48a2 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:41:37 -0300 Subject: [PATCH 06/30] Remove block processor (#169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Goes on top of https://github.com/flashbots/rbuilder/pull/168 ## 📝 Summary This PR removes the block processor and replaces it with a trait so anyone can hook into the delivered blocks. It solves the issue https://github.com/flashbots/rbuilder/issues/77. This was also a potential data leak. ## 💡 Motivation and Context The block processor was a very specific flashbots thing. --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable) --- config-live-example.toml | 3 - .../src/flashbots/blocks_processor.rs | 225 ------------------ crates/rbuilder/src/flashbots/mod.rs | 3 - crates/rbuilder/src/lib.rs | 1 - .../live_builder/block_output/bid_observer.rs | 33 +++ .../src/live_builder/block_output/mod.rs | 1 + .../live_builder/block_output/relay_submit.rs | 43 ++-- crates/rbuilder/src/live_builder/config.rs | 31 +-- crates/rbuilder/src/telemetry/metrics.rs | 9 - 9 files changed, 69 insertions(+), 280 deletions(-) delete mode 100644 crates/rbuilder/src/flashbots/blocks_processor.rs delete mode 100644 crates/rbuilder/src/flashbots/mod.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bid_observer.rs diff --git a/config-live-example.toml b/config-live-example.toml index f8479e56..f47642b6 100644 --- a/config-live-example.toml +++ b/config-live-example.toml @@ -21,9 +21,6 @@ blocklist_file_path = "./blocklist.json" dry_run = true dry_run_validation_url = "http://localhost:8545" -# blocks_processor_url can be an API service to record bids and transactions. It is not required. -# blocks_processor_url = "http://block_processor.internal" - ignore_cancellable_orders = true sbundle_mergeabe_signers = [] diff --git a/crates/rbuilder/src/flashbots/blocks_processor.rs b/crates/rbuilder/src/flashbots/blocks_processor.rs deleted file mode 100644 index c1ac527b..00000000 --- a/crates/rbuilder/src/flashbots/blocks_processor.rs +++ /dev/null @@ -1,225 +0,0 @@ -use crate::{ - building::BuiltBlockTrace, - mev_boost::SubmitBlockRequest, - primitives::{ - serialize::{RawBundle, RawShareBundle}, - Order, - }, - utils::{error_storage::store_error_event, http_provider, BoxedProvider}, -}; -use alloy_json_rpc::RpcError; -use alloy_primitives::{BlockHash, U256}; -use alloy_provider::Provider; -use reth_primitives::SealedBlock; -use serde::{Deserialize, Serialize}; -use serde_with::{serde_as, DisplayFromStr}; -use std::sync::Arc; -use time::format_description::well_known; -use tracing::{debug, error}; - -const BLOCK_PROCESSOR_ERROR_CATEGORY: &str = "block_processor"; - -#[derive(Debug, Clone)] -pub struct BlocksProcessorClient { - client: Arc, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct UsedSbundle { - bundle: RawShareBundle, - success: bool, -} - -#[serde_as] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct UsedBundle { - #[serde_as(as = "DisplayFromStr")] - mev_gas_price: U256, - #[serde_as(as = "DisplayFromStr")] - total_eth: U256, - #[serde_as(as = "DisplayFromStr")] - eth_send_to_coinbase: U256, - #[serde_as(as = "DisplayFromStr")] - total_gas_used: u64, - original_bundle: RawBundle, -} - -/// Header used by block_consumeBuiltBlockV2. Since docs are not up to date I copied RbuilderHeader from block-processor/ports/models.go (commit b341b35) -/// Based on alloy_primitives::Block -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] -#[serde(rename_all = "camelCase")] -struct BlocksProcessorHeader { - pub hash: BlockHash, - pub gas_limit: U256, - pub gas_used: U256, - #[serde(skip_serializing_if = "Option::is_none")] - pub base_fee_per_gas: Option, - pub parent_hash: BlockHash, - pub timestamp: U256, - pub number: Option, -} - -impl BlocksProcessorClient { - pub fn try_from(url: &str) -> eyre::Result { - Ok(Self { - client: Arc::new(http_provider(url.parse()?)), - }) - } - - pub async fn submit_built_block( - &self, - sealed_block: &SealedBlock, - submit_block_request: &SubmitBlockRequest, - built_block_trace: &BuiltBlockTrace, - builder_name: String, - best_bid_value: U256, - ) -> eyre::Result<()> { - let header = BlocksProcessorHeader { - hash: sealed_block.hash(), - gas_limit: U256::from(sealed_block.gas_limit), - gas_used: U256::from(sealed_block.gas_used), - base_fee_per_gas: sealed_block.base_fee_per_gas.map(U256::from), - parent_hash: sealed_block.parent_hash, - timestamp: U256::from(sealed_block.timestamp), - number: Some(U256::from(sealed_block.number)), - }; - let closed_at = built_block_trace - .orders_closed_at - .format(&well_known::Iso8601::DEFAULT)?; - let sealed_at = built_block_trace - .orders_sealed_at - .format(&well_known::Iso8601::DEFAULT)?; - - let committed_bundles = built_block_trace - .included_orders - .iter() - .filter_map(|res| { - if let Order::Bundle(bundle) = &res.order { - Some(UsedBundle { - mev_gas_price: res.inplace_sim.mev_gas_price, - total_eth: res.inplace_sim.coinbase_profit, - eth_send_to_coinbase: U256::ZERO, - total_gas_used: res.inplace_sim.gas_used, - original_bundle: RawBundle::encode_no_blobs(bundle.clone()), - }) - } else { - None - } - }) - .collect::>(); - - let used_share_bundles = Self::get_used_sbundles(built_block_trace); - - let params = ( - header, - closed_at, - sealed_at, - committed_bundles.clone(), - committed_bundles, - used_share_bundles, - submit_block_request.bid_trace(), - builder_name, - built_block_trace.true_bid_value, - best_bid_value, - ); - - match self - .client - .raw_request("block_consumeBuiltBlockV2".into(), ¶ms) - .await - { - Ok(()) => {} - Err(err) => { - match &err { - RpcError::ErrorResp(err) => { - error!(err = ?err, "Block processor returned error"); - store_error_event( - BLOCK_PROCESSOR_ERROR_CATEGORY, - &err.to_string(), - ¶ms, - ); - } - RpcError::SerError(err) => { - error!(err = ?err, "Failed to serialize block processor request"); - } - RpcError::DeserError { err, text } => { - if !(text.contains("504 Gateway Time-out") - || text.contains("502 Bad Gateway")) - { - error!(err = ?err, "Failed to deserialize block processor response"); - store_error_event( - BLOCK_PROCESSOR_ERROR_CATEGORY, - &err.to_string(), - ¶ms, - ); - } - } - RpcError::Transport(err) => { - debug!(err = ?err, "Failed to send block processor request"); - } - RpcError::NullResp => { - error!("Block processor returned null response"); - } - RpcError::UnsupportedFeature(err) => { - error!(err = ?err, "Unsupported feature"); - } - RpcError::LocalUsageError(err) => { - error!(err = ?err, "Local usage error"); - } - } - return Err(err.into()); - } - } - - Ok(()) - } - - /// Gets the UsedSbundle carefully considering virtual orders formed by other original orders. - fn get_used_sbundles(built_block_trace: &BuiltBlockTrace) -> Vec { - built_block_trace - .included_orders - .iter() - .flat_map(|exec_result| { - if let Order::ShareBundle(sbundle) = &exec_result.order { - // don't like having special cases (merged vs not merged), can we improve this? - let filtered_sbundles = if sbundle.is_merged_order() { - // We include only original orders that are contained in original_order_ids. - // If not contained in original_order_ids then the sub sbundle failed or was an empty execution. - sbundle - .original_orders - .iter() - .filter_map(|sub_order| { - if let Order::ShareBundle(sbundle) = sub_order { - if exec_result.original_order_ids.contains(&sub_order.id()) { - Some(sbundle) - } else { - None - } - } else { - None - } - }) - .collect() - } else if exec_result.txs.is_empty() { - // non merged empty execution sbundle - vec![] - } else { - // non merged non empty execution sbundle - vec![sbundle] - }; - filtered_sbundles - .into_iter() - .map(|sbundle| UsedSbundle { - bundle: RawShareBundle::encode_no_blobs(sbundle.clone()), - success: true, - }) - .collect() - } else { - Vec::new() - } - }) - .collect::>() - } -} diff --git a/crates/rbuilder/src/flashbots/mod.rs b/crates/rbuilder/src/flashbots/mod.rs deleted file mode 100644 index acc17f09..00000000 --- a/crates/rbuilder/src/flashbots/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod blocks_processor; - -pub use blocks_processor::BlocksProcessorClient; diff --git a/crates/rbuilder/src/lib.rs b/crates/rbuilder/src/lib.rs index d8cf49f9..7572d559 100644 --- a/crates/rbuilder/src/lib.rs +++ b/crates/rbuilder/src/lib.rs @@ -1,7 +1,6 @@ pub mod backtest; pub mod beacon_api_client; pub mod building; -pub mod flashbots; pub mod integration; pub mod live_builder; pub mod mev_boost; diff --git a/crates/rbuilder/src/live_builder/block_output/bid_observer.rs b/crates/rbuilder/src/live_builder/block_output/bid_observer.rs new file mode 100644 index 00000000..4049c546 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bid_observer.rs @@ -0,0 +1,33 @@ +use alloy_primitives::U256; +use reth_primitives::SealedBlock; + +use crate::{building::BuiltBlockTrace, mev_boost::SubmitBlockRequest}; + +/// Trait that receives every bid made to the relays. +pub trait BidObserver: std::fmt::Debug { + /// This callback is executed after the bid was made so it gives away ownership of the data. + /// This should NOT block since it's executed in the submitting thread. + fn block_submitted( + &self, + sealed_block: SealedBlock, + submit_block_request: SubmitBlockRequest, + built_block_trace: BuiltBlockTrace, + builder_name: String, + best_bid_value: U256, + ); +} + +#[derive(Debug)] +pub struct NullBidObserver {} + +impl BidObserver for NullBidObserver { + fn block_submitted( + &self, + _sealed_block: SealedBlock, + _submit_block_request: SubmitBlockRequest, + _built_block_trace: BuiltBlockTrace, + _builder_name: String, + _best_bid_value: U256, + ) { + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/mod.rs b/crates/rbuilder/src/live_builder/block_output/mod.rs index cb21101c..fcd5de14 100644 --- a/crates/rbuilder/src/live_builder/block_output/mod.rs +++ b/crates/rbuilder/src/live_builder/block_output/mod.rs @@ -1,3 +1,4 @@ +pub mod bid_observer; pub mod bidding; mod block_finisher; pub mod block_finisher_factory; diff --git a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs index 9504a15c..1b9d3c86 100644 --- a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs +++ b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs @@ -1,13 +1,12 @@ use crate::{ building::builders::Block, - flashbots::BlocksProcessorClient, live_builder::payload_events::MevBoostSlotData, mev_boost::{ sign_block_for_relay, BLSBlockSigner, RelayError, SubmitBlockErr, SubmitBlockRequest, }, primitives::mev_boost::{MevBoostRelay, MevBoostRelayID}, telemetry::{ - add_relay_submit_time, add_subsidy_value, inc_blocks_api_errors, inc_conn_relay_errors, + add_relay_submit_time, add_subsidy_value, inc_conn_relay_errors, inc_failed_block_simulations, inc_initiated_submissions, inc_other_relay_errors, inc_relay_accepted_submissions, inc_subsidized_blocks, inc_too_many_req_relay_errors, measure_block_e2e_latency, @@ -28,6 +27,8 @@ use tokio::time::{sleep, Instant}; use tokio_util::sync::CancellationToken; use tracing::{debug, error, info_span, trace, warn, Instrument}; +use super::bid_observer::BidObserver; + const SIM_ERROR_CATEGORY: &str = "submit_block_simulation"; const VALIDATION_ERROR_CATEGORY: &str = "validate_block_simulation"; @@ -101,7 +102,7 @@ pub trait BuilderSinkFactory: std::fmt::Debug + Send + Sync { ) -> Box; } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct SubmissionConfig { pub chain_spec: Arc, pub signer: BLSBlockSigner, @@ -114,7 +115,7 @@ pub struct SubmissionConfig { pub optimistic_max_bid_value: U256, pub optimistic_prevalidate_optimistic_blocks: bool, - pub blocks_processor: Option, + pub bid_observer: Box, /// Delta relative to slot_time at which we start to submit blocks. Usually negative since we need to start submitting BEFORE the slot time. pub slot_delta_to_start_submits: time::Duration, } @@ -143,7 +144,7 @@ async fn run_submit_to_relays_job( best_bid: BestBlockCell, slot_data: MevBoostSlotData, relays: Vec, - config: SubmissionConfig, + config: Arc, cancel: CancellationToken, bid_source: Arc, ) -> Option { @@ -376,22 +377,16 @@ async fn run_submit_to_relays_job( } } - if let Some(blocks_processor) = config.blocks_processor.clone() { - let cancel = cancel.clone(); - tokio::spawn(async move { - let block_processor_result = tokio::select! { - _ = cancel.cancelled() => { - return; - }, - // NOTE: we only store normal submission here because they have the same contents but different pubkeys - res = blocks_processor.submit_built_block(&block.sealed_block, &normal_signed_submission, &block.trace, builder_name, best_bid_value) => res - }; - if let Err(err) = block_processor_result { - inc_blocks_api_errors(); - warn!(parent: &submission_span, "Failed to submit block to the blocks api: {}", err); - } - }); - } + submission_span.in_scope(|| { + // NOTE: we only notify normal submission here because they have the same contents but different pubkeys + config.bid_observer.block_submitted( + block.sealed_block, + normal_signed_submission, + block.trace, + builder_name, + best_bid_value, + ); + }) } } @@ -399,7 +394,7 @@ pub async fn run_submit_to_relays_job_and_metrics( best_bid: BestBlockCell, slot_data: MevBoostSlotData, relays: Vec, - config: SubmissionConfig, + config: Arc, cancel: CancellationToken, bid_source: Arc, ) { @@ -520,7 +515,7 @@ async fn submit_bid_to_the_relay( /// Real life BuilderSinkFactory that send the blocks to the Relay #[derive(Debug)] pub struct RelaySubmitSinkFactory { - submission_config: SubmissionConfig, + submission_config: Arc, relays: HashMap, } @@ -531,7 +526,7 @@ impl RelaySubmitSinkFactory { .map(|relay| (relay.id.clone(), relay)) .collect(); Self { - submission_config, + submission_config: Arc::new(submission_config), relays, } } diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index 1c4b5c40..2cc364a0 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -3,7 +3,10 @@ //! use super::{ base_config::BaseConfig, - block_output::relay_submit::{RelaySubmitSinkFactory, SubmissionConfig}, + block_output::{ + bid_observer::{BidObserver, NullBidObserver}, + relay_submit::{RelaySubmitSinkFactory, SubmissionConfig}, + }, }; use crate::{ beacon_api_client::Client, @@ -14,7 +17,6 @@ use crate::{ }, Sorting, }, - flashbots::BlocksProcessorClient, live_builder::{ base_config::EnvOrValue, block_output::{ @@ -106,7 +108,6 @@ pub struct L1Config { pub optimistic_max_bid_value_eth: String, /// If true all optimistic submissions will be validated on nodes specified in `dry_run_validation_url` pub optimistic_prevalidate_optimistic_blocks: bool, - pub blocks_processor_url: Option, // See [`SubmissionConfig`] slot_delta_to_start_submits_ms: Option, @@ -127,7 +128,6 @@ impl Default for L1Config { optimistic_enabled: false, optimistic_max_bid_value_eth: "0.0".to_string(), optimistic_prevalidate_optimistic_blocks: false, - blocks_processor_url: None, slot_delta_to_start_submits_ms: None, cl_node_url: vec![EnvOrValue::from("http://127.0.0.1:3500")], } @@ -182,7 +182,11 @@ impl L1Config { .unwrap_or(DEFAULT_SLOT_DELTA_TO_START_SUBMITS) } - fn submission_config(&self, chain_spec: Arc) -> eyre::Result { + fn submission_config( + &self, + chain_spec: Arc, + bid_observer: Box, + ) -> eyre::Result { if (self.dry_run || self.optimistic_prevalidate_optimistic_blocks) && self.dry_run_validation_url.is_empty() { @@ -226,13 +230,8 @@ impl L1Config { optimistic_signer, optimistic_max_bid_value: parse_ether(&self.optimistic_max_bid_value_eth)?, optimistic_prevalidate_optimistic_blocks: self.optimistic_prevalidate_optimistic_blocks, - blocks_processor: if let Some(url) = &self.blocks_processor_url { - let client = BlocksProcessorClient::try_from(url)?; - Some(client) - } else { - None - }, slot_delta_to_start_submits: self.slot_delta_to_start_submits(), + bid_observer, }) } @@ -240,8 +239,9 @@ impl L1Config { pub fn create_relays_sealed_sink_factory( &self, chain_spec: Arc, + bid_observer: Box, ) -> eyre::Result<(Box, Vec)> { - let submission_config = self.submission_config(chain_spec)?; + let submission_config = self.submission_config(chain_spec, bid_observer)?; info!( "Builder mev boost normal relay pubkey: {:?}", submission_config.signer.pub_key() @@ -275,9 +275,10 @@ impl LiveBuilderConfig for Config { &self, cancellation_token: tokio_util::sync::CancellationToken, ) -> eyre::Result, MevBoostSlotDataGenerator>> { - let (sink_sealed_factory, relays) = self - .l1_config - .create_relays_sealed_sink_factory(self.base_config.chain_spec()?)?; + let (sink_sealed_factory, relays) = self.l1_config.create_relays_sealed_sink_factory( + self.base_config.chain_spec()?, + Box::new(NullBidObserver {}), + )?; let sink_factory = Box::new(BlockFinisherFactory::new( Box::new(DummyBiddingService {}), sink_sealed_factory, diff --git a/crates/rbuilder/src/telemetry/metrics.rs b/crates/rbuilder/src/telemetry/metrics.rs index f51991d1..4f3d3eae 100644 --- a/crates/rbuilder/src/telemetry/metrics.rs +++ b/crates/rbuilder/src/telemetry/metrics.rs @@ -108,11 +108,6 @@ register_metrics! { &[] ) .unwrap(); - pub static BLOCK_API_ERRORS: IntCounterVec = IntCounterVec::new( - Opts::new("block_api_errors", "counter of the block processor errors"), - &[] - ) - .unwrap(); pub static SIMULATED_OK_ORDERS: IntCounter = IntCounter::new("simulated_ok_orders", "Simulated succeeded orders").unwrap(); pub static SIMULATED_FAILED_ORDERS: IntCounter = @@ -248,10 +243,6 @@ pub fn inc_failed_block_simulations() { BLOCK_SIM_ERRORS.with_label_values(&[]).inc() } -pub fn inc_blocks_api_errors() { - BLOCK_API_ERRORS.with_label_values(&[]).inc() -} - pub fn set_current_block(block: u64) { CURRENT_BLOCK.set(block as i64); } From 59e7cd3f389a98d02e2267cbb0457f6c10caa72d Mon Sep 17 00:00:00 2001 From: liamaharon Date: Wed, 11 Sep 2024 04:25:57 +1000 Subject: [PATCH 07/30] `redacted` and `full` telemetry servers (#164) - ~Creates a new module `server` inside `live_builder`~ - ~Server exposes a single fn `start`, which starts an actix server on the given port~ - ~Initial server implementation just exposes one route `/health` that responds 200~ - ~Adds new base config item `live_builder_server_port`~ - ~Server is spawned when running the `live_builder` cli~ ## Background - TDX builders cannot expose the existing telemetry server port, due to concerns about sensitive operational information leakage. This information may require a time-delay or additional sanitisation before being exposed outside of the secure machine. - TDX builders require some other means to know if the builder is healthy or not. ## Solution - Separated the telemetry server into two servers: `full` and `redacted`. - `full`: what we have now, exposes all operational data without regard for whether it is sensitive - `redacted`: new server that initially only exposes a healthcheck endpoint (can be extended later). This server is safe to always be exposed by tdx builders. --- config-live-example.toml | 6 +- config-playground.toml | 6 +- .../rbuilder/src/live_builder/base_config.rs | 34 +++++++-- crates/rbuilder/src/live_builder/cli.rs | 11 ++- crates/rbuilder/src/telemetry/mod.rs | 73 ++---------------- crates/rbuilder/src/telemetry/servers/full.rs | 76 +++++++++++++++++++ crates/rbuilder/src/telemetry/servers/mod.rs | 13 ++++ .../src/telemetry/servers/redacted.rs | 19 +++++ 8 files changed, 156 insertions(+), 82 deletions(-) create mode 100644 crates/rbuilder/src/telemetry/servers/full.rs create mode 100644 crates/rbuilder/src/telemetry/servers/mod.rs create mode 100644 crates/rbuilder/src/telemetry/servers/redacted.rs diff --git a/config-live-example.toml b/config-live-example.toml index f47642b6..9aa3ce6f 100644 --- a/config-live-example.toml +++ b/config-live-example.toml @@ -1,7 +1,9 @@ log_json = true log_level = "info,rbuilder=debug" -telemetry_port = 6060 -telemetry_ip = "0.0.0.0" +redacted_telemetry_server_port = 6061 +redacted_telemetry_server_ip = "0.0.0.0" +full_telemetry_server_port = 6060 +full_telemetry_server_ip = "0.0.0.0" chain = "mainnet" reth_datadir = "/mnt/data/reth" diff --git a/config-playground.toml b/config-playground.toml index ecd94aef..89e900bb 100644 --- a/config-playground.toml +++ b/config-playground.toml @@ -1,7 +1,9 @@ log_json = false log_level = "info,rbuilder=debug" -telemetry_port = 6060 -telemetry_ip = "0.0.0.0" +redacted_telemetry_server_port = 6061 +redacted_telemetry_server_ip = "0.0.0.0" +full_telemetry_server_port = 6060 +full_telemetry_server_ip = "0.0.0.0" chain = "$HOME/.playground/devnet/genesis.json" reth_datadir = "$HOME/.playground/devnet/data_reth" diff --git a/crates/rbuilder/src/live_builder/base_config.rs b/crates/rbuilder/src/live_builder/base_config.rs index 40d4081f..3496738d 100644 --- a/crates/rbuilder/src/live_builder/base_config.rs +++ b/crates/rbuilder/src/live_builder/base_config.rs @@ -43,8 +43,10 @@ const ENV_PREFIX: &str = "env:"; #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] #[serde(default, deny_unknown_fields)] pub struct BaseConfig { - pub telemetry_port: u16, - pub telemetry_ip: Option, + pub full_telemetry_server_port: u16, + pub full_telemetry_server_ip: Option, + pub redacted_telemetry_server_port: u16, + pub redacted_telemetry_server_ip: Option, pub log_json: bool, log_level: EnvOrValue, pub log_color: bool, @@ -141,8 +143,18 @@ impl BaseConfig { Ok(()) } - pub fn telemetry_address(&self) -> SocketAddr { - SocketAddr::V4(SocketAddrV4::new(self.telemetry_ip(), self.telemetry_port)) + pub fn redacted_telemetry_server_address(&self) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new( + self.redacted_telemetry_server_ip(), + self.redacted_telemetry_server_port, + )) + } + + pub fn full_telemetry_server_address(&self) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new( + self.full_telemetry_server_ip(), + self.full_telemetry_server_port, + )) } /// WARN: opens reth db @@ -201,8 +213,12 @@ impl BaseConfig { parse_ip(&self.jsonrpc_server_ip) } - pub fn telemetry_ip(&self) -> Ipv4Addr { - parse_ip(&self.telemetry_ip) + pub fn redacted_telemetry_server_ip(&self) -> Ipv4Addr { + parse_ip(&self.redacted_telemetry_server_ip) + } + + pub fn full_telemetry_server_ip(&self) -> Ipv4Addr { + parse_ip(&self.full_telemetry_server_ip) } pub fn chain_spec(&self) -> eyre::Result> { @@ -366,8 +382,10 @@ pub const DEFAULT_RETH_DB_PATH: &str = "/mnt/data/reth"; impl Default for BaseConfig { fn default() -> Self { Self { - telemetry_port: 6069, - telemetry_ip: None, + full_telemetry_server_port: 6069, + full_telemetry_server_ip: None, + redacted_telemetry_server_port: 6070, + redacted_telemetry_server_ip: None, log_json: false, log_level: "info".into(), log_color: false, diff --git a/crates/rbuilder/src/live_builder/cli.rs b/crates/rbuilder/src/live_builder/cli.rs index a165c0b8..229f3a99 100644 --- a/crates/rbuilder/src/live_builder/cli.rs +++ b/crates/rbuilder/src/live_builder/cli.rs @@ -11,7 +11,7 @@ use crate::{ live_builder::{ base_config::load_config_toml_and_env, payload_events::MevBoostSlotDataGenerator, }, - telemetry::spawn_telemetry_server, + telemetry, utils::build_info::Version, }; @@ -80,8 +80,13 @@ pub async fn run( let cancel = CancellationToken::new(); - spawn_telemetry_server( - config.base_config().telemetry_address(), + // Spawn redacted server that is safe for tdx builders to expose + telemetry::servers::redacted::spawn(config.base_config().redacted_telemetry_server_address()) + .await?; + + // Spawn debug server that exposes detailed operational information + telemetry::servers::full::spawn( + config.base_config().full_telemetry_server_address(), config.version_for_telemetry(), ) .await?; diff --git a/crates/rbuilder/src/telemetry/mod.rs b/crates/rbuilder/src/telemetry/mod.rs index 179e449f..34904b07 100644 --- a/crates/rbuilder/src/telemetry/mod.rs +++ b/crates/rbuilder/src/telemetry/mod.rs @@ -1,73 +1,12 @@ -//! Telemetry helps track what is happening in the running application using metrics and tracing. +//! Telemetry modules helps tracking what is happening in the rbuilder. //! -//! Interface to telemetry should be set of simple functions like: -//! fn record_event(event_data) -//! All internals are global variables. - -use serde::Deserialize; -use std::{net::SocketAddr, path::PathBuf}; -use tracing::{info, warn}; -use warp::{Filter, Rejection, Reply}; +//! The redacted server is seperate from the full server, because it may be desirable +//! to expose full and redacted data differently in tdx builders. e.g. redacted data +//! immediately avaliable, and full data avaliable after a delay or some seperate sanitisation. mod dynamic_logs; -pub mod metrics; +mod metrics; +pub mod servers; pub use dynamic_logs::*; pub use metrics::*; - -use crate::utils::build_info::Version; - -async fn metrics_handler() -> Result { - Ok(gather_prometheus_metrics()) -} - -#[derive(Debug, Deserialize)] -struct LogQuery { - file: Option, -} - -async fn set_rust_log_handle( - rust_log: String, - log_query: LogQuery, -) -> Result { - info!(?rust_log, ?log_query, "Setting log level"); - let mut log_config = default_log_config(); - log_config.file.clone_from(&log_query.file); - log_config.env_filter.clone_from(&rust_log); - match set_log_config(log_config) { - Ok(_) => Ok("".to_string()), - Err(err) => { - warn!(?err, ?rust_log, ?log_query, "Failed to set log level"); - Ok(err.to_string()) - } - } -} - -async fn reset_log_handle() -> Result { - info!("Resetting log level"); - match reset_log_config() { - Ok(_) => Ok("".to_string()), - Err(err) => { - warn!(?err, "Failed to reset log level"); - Ok(err.to_string()) - } - } -} - -pub async fn spawn_telemetry_server(addr: SocketAddr, version: Version) -> eyre::Result<()> { - set_version(version); - - // metrics over /debug/metrics/prometheus - let metrics_route = warp::path!("debug" / "metrics" / "prometheus").and_then(metrics_handler); - - let log_set_route = warp::path!("debug" / "log" / "set" / String) - .and(warp::query::()) - .and_then(set_rust_log_handle); - let log_reset_route = warp::path!("debug" / "log" / "reset").and_then(reset_log_handle); - - let route = metrics_route.or(log_set_route).or(log_reset_route); - - tokio::spawn(warp::serve(route).run(addr)); - - Ok(()) -} diff --git a/crates/rbuilder/src/telemetry/servers/full.rs b/crates/rbuilder/src/telemetry/servers/full.rs new file mode 100644 index 00000000..6fa842e7 --- /dev/null +++ b/crates/rbuilder/src/telemetry/servers/full.rs @@ -0,0 +1,76 @@ +//! Telemetry helps track what is happening in the running application using metrics and tracing. +//! +//! Interface to telemetry should be set of simple functions like: +//! fn record_event(event_data) +//! +//! All internals are global variables. +//! +//! Full server may expose metrics that could leak information when running tdx. + +use serde::Deserialize; +use std::{net::SocketAddr, path::PathBuf}; +use tracing::{info, warn}; +use warp::{Filter, Rejection, Reply}; + +use crate::{ + telemetry::{ + dynamic_logs::{default_log_config, reset_log_config, set_log_config}, + metrics::{gather_prometheus_metrics, set_version}, + }, + utils::build_info::Version, +}; + +pub async fn spawn(addr: SocketAddr, version: Version) -> eyre::Result<()> { + set_version(version); + + // metrics over /debug/metrics/prometheus + let metrics_route = warp::path!("debug" / "metrics" / "prometheus").and_then(metrics_handler); + + let log_set_route = warp::path!("debug" / "log" / "set" / String) + .and(warp::query::()) + .and_then(set_rust_log_handle); + let log_reset_route = warp::path!("debug" / "log" / "reset").and_then(reset_log_handle); + + let route = metrics_route.or(log_set_route).or(log_reset_route); + + tokio::spawn(warp::serve(route).run(addr)); + + Ok(()) +} + +async fn metrics_handler() -> Result { + Ok(gather_prometheus_metrics()) +} + +#[derive(Debug, Deserialize)] +struct LogQuery { + file: Option, +} + +async fn set_rust_log_handle( + rust_log: String, + log_query: LogQuery, +) -> Result { + info!(?rust_log, ?log_query, "Setting log level"); + let mut log_config = default_log_config(); + log_config.file.clone_from(&log_query.file); + log_config.env_filter.clone_from(&rust_log); + match set_log_config(log_config) { + Ok(_) => Ok("".to_string()), + Err(err) => { + warn!(?err, ?rust_log, ?log_query, "Failed to set log level"); + Ok(err.to_string()) + } + } +} + +async fn reset_log_handle() -> Result { + info!("Resetting log level"); + match reset_log_config() { + Ok(_) => Ok("".to_string()), + Err(err) => { + warn!(?err, "Failed to reset log level"); + Ok(err.to_string()) + } + } +} diff --git a/crates/rbuilder/src/telemetry/servers/mod.rs b/crates/rbuilder/src/telemetry/servers/mod.rs new file mode 100644 index 00000000..94665cfd --- /dev/null +++ b/crates/rbuilder/src/telemetry/servers/mod.rs @@ -0,0 +1,13 @@ +//! Telemetry contains two servers. +//! +//! - [full]: verbose server exposing detailed operational information about the +//! builder. +//! - [redacted]: deliberately redacted server serves information suitable for +//! tdx builders to expose in real-time. +//! +//! The redacted server is seperate from the debug server because it may be desirable +//! to expose debug and redacted data differently in tdx builders. e.g. redacted data +//! immediately avaliable, debug data avaliable after a delay or some seperate sanitisation. + +pub mod full; +pub mod redacted; diff --git a/crates/rbuilder/src/telemetry/servers/redacted.rs b/crates/rbuilder/src/telemetry/servers/redacted.rs new file mode 100644 index 00000000..2d29b669 --- /dev/null +++ b/crates/rbuilder/src/telemetry/servers/redacted.rs @@ -0,0 +1,19 @@ +//! Server that only exposes redacted data, suitable for being exposed by tdx +//! builders in real-time. +//! +//! Currently exposes just a healthcheck endpoint on /health. Can be extended +//! in the future. + +use std::net::SocketAddr; + +use warp::{Filter, Rejection, Reply}; + +async fn handler() -> Result { + Ok("OK") +} + +pub async fn spawn(addr: SocketAddr) -> eyre::Result<()> { + let route = warp::path!("health").and_then(handler); + tokio::spawn(warp::serve(route).run(addr)); + Ok(()) +} From ea64a8a48ca38e82d90da2437ade92a3f55a13fa Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:40:09 -0300 Subject: [PATCH 08/30] Dynamic log optional (#171) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Goes on top of https://github.com/flashbots/rbuilder/pull/169. ## 📝 Summary Allows to disable dynamic logs. ## 💡 Motivation and Context In some contexts (eg: TEE) they might be a security leak. --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable) --- .../rbuilder/src/live_builder/base_config.rs | 3 +++ crates/rbuilder/src/live_builder/cli.rs | 1 + crates/rbuilder/src/telemetry/servers/full.rs | 23 +++++++++++-------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/crates/rbuilder/src/live_builder/base_config.rs b/crates/rbuilder/src/live_builder/base_config.rs index 3496738d..cc2c0a8f 100644 --- a/crates/rbuilder/src/live_builder/base_config.rs +++ b/crates/rbuilder/src/live_builder/base_config.rs @@ -50,6 +50,8 @@ pub struct BaseConfig { pub log_json: bool, log_level: EnvOrValue, pub log_color: bool, + /// Enables dynamic logging (saving logs to a file) + pub log_enable_dynamic: bool, pub error_storage_path: Option, @@ -389,6 +391,7 @@ impl Default for BaseConfig { log_json: false, log_level: "info".into(), log_color: false, + log_enable_dynamic: false, error_storage_path: None, coinbase_secret_key: "".into(), flashbots_db: None, diff --git a/crates/rbuilder/src/live_builder/cli.rs b/crates/rbuilder/src/live_builder/cli.rs index 229f3a99..8547cd8f 100644 --- a/crates/rbuilder/src/live_builder/cli.rs +++ b/crates/rbuilder/src/live_builder/cli.rs @@ -88,6 +88,7 @@ pub async fn run( telemetry::servers::full::spawn( config.base_config().full_telemetry_server_address(), config.version_for_telemetry(), + config.base_config().log_enable_dynamic, ) .await?; let builder = config.create_builder(cancel.clone()).await?; diff --git a/crates/rbuilder/src/telemetry/servers/full.rs b/crates/rbuilder/src/telemetry/servers/full.rs index 6fa842e7..6193b35a 100644 --- a/crates/rbuilder/src/telemetry/servers/full.rs +++ b/crates/rbuilder/src/telemetry/servers/full.rs @@ -20,20 +20,25 @@ use crate::{ utils::build_info::Version, }; -pub async fn spawn(addr: SocketAddr, version: Version) -> eyre::Result<()> { +pub async fn spawn( + addr: SocketAddr, + version: Version, + enable_dynamic_log: bool, +) -> eyre::Result<()> { set_version(version); // metrics over /debug/metrics/prometheus let metrics_route = warp::path!("debug" / "metrics" / "prometheus").and_then(metrics_handler); - let log_set_route = warp::path!("debug" / "log" / "set" / String) - .and(warp::query::()) - .and_then(set_rust_log_handle); - let log_reset_route = warp::path!("debug" / "log" / "reset").and_then(reset_log_handle); - - let route = metrics_route.or(log_set_route).or(log_reset_route); - - tokio::spawn(warp::serve(route).run(addr)); + if enable_dynamic_log { + let log_set_route = warp::path!("debug" / "log" / "set" / String) + .and(warp::query::()) + .and_then(set_rust_log_handle); + let log_reset_route = warp::path!("debug" / "log" / "reset").and_then(reset_log_handle); + tokio::spawn(warp::serve(metrics_route.or(log_set_route).or(log_reset_route)).run(addr)); + } else { + tokio::spawn(warp::serve(metrics_route).run(addr)); + } Ok(()) } From 12ece403ee0d34f9b7918bb6c579c341888ce91a Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Thu, 12 Sep 2024 12:46:42 +0200 Subject: [PATCH 09/30] reth v1.0.6 (#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Updates reth to v1.0.6 it was tested in backtest on 1.5k block and outputs are identical ## 💡 Motivation and Context --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [x] Added tests (if applicable) --- Cargo.lock | 2722 +++++++---------- Cargo.toml | 76 +- .../benches/benchmarks/txpool_fetcher.rs | 9 +- .../src/backtest/backtest_build_block.rs | 3 +- crates/rbuilder/src/backtest/fetch/mod.rs | 6 +- .../src/backtest/redistribute/cli/mod.rs | 2 +- .../rbuilder/src/backtest/redistribute/mod.rs | 4 +- crates/rbuilder/src/backtest/store.rs | 7 +- crates/rbuilder/src/building/mod.rs | 6 +- .../order_input/clean_orderpool.rs | 2 +- 10 files changed, 1100 insertions(+), 1737 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa70d501..84ed2ac7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,26 +19,14 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aead" -version = "0.4.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ + "crypto-common", "generic-array", ] -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher 0.3.0", - "cpufeatures", - "ctr 0.8.0", - "opaque-debug", -] - [[package]] name = "aes" version = "0.8.4" @@ -46,20 +34,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", - "cipher 0.4.4", + "cipher", "cpufeatures", ] [[package]] name = "aes-gcm" -version = "0.9.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", - "aes 0.7.5", - "cipher 0.3.0", - "ctr 0.7.0", + "aes", + "cipher", + "ctr", "ghash", "subtle", ] @@ -123,44 +111,31 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58047cc851e58c26224521d1ecda466e3d746ebca0274cd5427aa660a88c353" +checksum = "4177d135789e282e925092be8939d421b701c6d92c0a16679faa659d9166289d" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-eips", + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-serde", "arbitrary", "c-kzg", "serde", ] -[[package]] -name = "alloy-consensus" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "c-kzg", - "serde", -] - [[package]] name = "alloy-dyn-abi" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" +checksum = "ba5b68572f5dfa99ede0a491d658c9842626c956b840d0b97d0bbc9637742504" dependencies = [ "alloy-json-abi", - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-sol-type-parser", "alloy-sol-types", "const-hex", - "derive_more", + "derive_more 0.99.18", "itoa", "serde", "serde_json", @@ -168,33 +143,46 @@ dependencies = [ ] [[package]] -name = "alloy-eips" -version = "0.2.0" +name = "alloy-eip2930" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a3e14fa0d152d00bd8daf605eb74ad397efb0f54bd7155585823dddb4401e" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", + "alloy-rlp", + "arbitrary", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d319bb544ca6caeab58c39cea8921c55d924d4f68f2c60f24f914673f9a74a" +dependencies = [ + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "arbitrary", - "c-kzg", - "derive_more", "k256 0.13.3", - "once_cell", + "rand 0.8.5", "serde", - "sha2 0.10.8", ] [[package]] name = "alloy-eips" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "499ee14d296a133d142efd215eb36bf96124829fe91cf8f5d4e5ccdd381eae00" dependencies = [ - "alloy-primitives", + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-serde", + "arbitrary", "c-kzg", - "derive_more", + "derive_more 1.0.0", "ethereum_ssz", "ethereum_ssz_derive", "once_cell", @@ -204,32 +192,22 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cb76c8a3913f2466c5488f3a915e3a15d15596bdc935558c1a9be75e9ec508" -dependencies = [ - "alloy-primitives", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde", -] - -[[package]] -name = "alloy-genesis" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +checksum = "4b85dfc693e4a1193f0372a8f789df12ab51fcbe7be0733baa04939a86dd813b" dependencies = [ - "alloy-primitives", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-primitives 0.8.0", + "alloy-serde", "serde", ] [[package]] name = "alloy-json-abi" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" +checksum = "299d2a937b6c60968df3dad2a988b0f0e03277b344639a4f7a31bd68e6285e59" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-sol-type-parser", "serde", "serde_json", @@ -237,23 +215,11 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a9feec2352c78545d1a37415699817bae8dc41654bd1bfe57d6cdd5433bd" +checksum = "4207166c79cfdf7f3bed24bbc84f5c7c5d4db1970f8c82e3fcc76257f16d2166" dependencies = [ - "alloy-primitives", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-json-rpc" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-sol-types", "serde", "serde_json", @@ -263,17 +229,18 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3223d71dc78f464b2743418d0be8b5c894313e272105a6206ad5e867d67b3ce2" +checksum = "dfbe2802d5b8c632f18d68c352073378f02a3407c1b6a4487194e7d21ab0f002" dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-json-rpc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-signer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives 0.8.0", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", "alloy-sol-types", "async-trait", "auto_impl", @@ -282,31 +249,24 @@ dependencies = [ ] [[package]] -name = "alloy-network" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-consensus 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-rpc-types-eth 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-signer 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-sol-types", - "async-trait", - "auto_impl", - "futures-utils-wasm", - "thiserror", +name = "alloy-network-primitives" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396c07726030fa0f9dab5da8c71ccd69d5eb74a7fe1072b7ae453a67e4fe553e" +dependencies = [ + "alloy-primitives 0.8.0", + "alloy-serde", + "serde", ] [[package]] name = "alloy-node-bindings" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c847311cc7386684ef38ab404069d795bee07da945f63d884265436870a17276" dependencies = [ - "alloy-genesis 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", + "alloy-genesis", + "alloy-primitives 0.8.0", "k256 0.13.3", "serde_json", "tempfile", @@ -322,20 +282,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" dependencies = [ "alloy-rlp", - "arbitrary", "bytes", "cfg-if", "const-hex", - "derive_arbitrary", - "derive_more", - "ethereum_ssz", - "getrandom 0.2.15", + "derive_more 0.99.18", "hex-literal", "itoa", "k256 0.13.3", "keccak-asm", "proptest", - "proptest-derive 0.4.0", "rand 0.8.5", "ruint", "serde", @@ -343,60 +298,55 @@ dependencies = [ ] [[package]] -name = "alloy-provider" -version = "0.2.0" +name = "alloy-primitives" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29da7457d853cb8199ec04b227d5d2ef598be3e59fc2bbad70c8be213292f32" +checksum = "a767e59c86900dd7c3ce3ecef04f3ace5ac9631ee150beb8b7d22f7fa3bbb2d7" dependencies = [ - "alloy-chains", - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-json-rpc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-network 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-pubsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-rpc-client 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport-http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport-ws", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "futures", - "futures-utils-wasm", - "lru", - "pin-project", - "reqwest 0.12.5", + "alloy-rlp", + "arbitrary", + "bytes", + "cfg-if", + "const-hex", + "derive_arbitrary", + "derive_more 0.99.18", + "getrandom 0.2.15", + "hex-literal", + "itoa", + "k256 0.13.3", + "keccak-asm", + "proptest", + "proptest-derive", + "rand 0.8.5", + "ruint", "serde", - "serde_json", - "tokio", - "tracing", - "url", + "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1376948df782ffee83a54cac4b2aba14134edd997229a3db97da0a606586eb5c" dependencies = [ "alloy-chains", - "alloy-consensus 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-network 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-pubsub 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-rpc-client 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-rpc-types-eth 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport-http 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives 0.8.0", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-transport", + "alloy-transport-http", "alloy-transport-ipc", + "alloy-transport-ws", "async-stream", "async-trait", "auto_impl", - "dashmap", + "dashmap 6.0.1", "futures", "futures-utils-wasm", "lru", @@ -404,6 +354,7 @@ dependencies = [ "reqwest 0.12.5", "serde", "serde_json", + "thiserror", "tokio", "tracing", "url", @@ -411,31 +362,13 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64acfec654ade392cecfa9bba0408eb2a337d55f1b857925da79970cb70f3d6" +checksum = "fa73f976e7b6341f3f8a404241cf04f883d40212cd4f2633c66d99de472e262c" dependencies = [ - "alloy-json-rpc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-transport 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bimap", - "futures", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", -] - -[[package]] -name = "alloy-pubsub" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-transport 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-json-rpc", + "alloy-primitives 0.8.0", + "alloy-transport", "bimap", "futures", "serde", @@ -470,39 +403,17 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a9e609524fa31c2c70eb24c0da60796809193ad4787a6dfe6d0db0d3ac112d" +checksum = "02378418a429f8a14a0ad8ffaa15b2d25ff34914fc4a1e366513c6a3800e03b3" dependencies = [ - "alloy-json-rpc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-pubsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport-http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport-ws", - "futures", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-rpc-client" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-pubsub 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport-http 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-json-rpc", + "alloy-primitives 0.8.0", + "alloy-pubsub", + "alloy-transport", + "alloy-transport-http", "alloy-transport-ipc", + "alloy-transport-ws", "futures", "pin-project", "reqwest 0.12.5", @@ -517,72 +428,49 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5d76f1e8b22f48b7b8f985782b68e7eb3938780e50e8b646a53e41a598cdf5" +checksum = "d9ae4c4fbd37d9996f501fbc7176405aab97ae3a5772789be06ef0e7c4dad6dd" dependencies = [ - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", "alloy-rpc-types-trace", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-rpc-types-eth 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-serde", "serde", ] [[package]] name = "alloy-rpc-types-admin" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "137f0014c3a61ccc5168289fcc214d7296c389c0bf60425c0f898cff1d7e4bec" +checksum = "594b7cb723759c7b438c95a3bbd2e391760c03ee857443070758aaf2593ae84e" dependencies = [ - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-genesis", + "alloy-primitives 0.8.0", "serde", "serde_json", ] [[package]] name = "alloy-rpc-types-anvil" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4282c002a4ae9f57887dae57083fcca6dca09cb6685bf98b8582ea93cb3df97d" +checksum = "140b079c6fda14d9586432bf988b46ac0e04871ca313c9e00aa85cc808105e8a" dependencies = [ - "alloy-primitives", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-primitives 0.8.0", + "alloy-serde", "serde", ] [[package]] name = "alloy-rpc-types-beacon" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b47dcc8e3bebea57b1c9495a7e6f3313e99d355c0f5b80473cfbdfcbdd6ebea" -dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde", - "serde_with", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-beacon" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +checksum = "abbd9b6764423821bd6874477791ca68cfd0e946958d611319b57b006edf0113" dependencies = [ - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-rpc-types-engine 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-eips", + "alloy-primitives 0.8.0", + "alloy-rpc-types-engine", "ethereum_ssz", "ethereum_ssz_derive", "serde", @@ -592,36 +480,19 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73445fbc5c02258e3d0d977835c92366a4d91545fd456c3fc8601c61810bc9f6" -dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpsee-types 0.23.2", - "jsonwebtoken", - "rand 0.8.5", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-engine" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +checksum = "d79cadb52e32d40afa04847647eb50a332559d7870e66e46a0c32c33bf1c801d" dependencies = [ - "alloy-consensus 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", + "alloy-consensus", + "alloy-eips", + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-rpc-types-eth 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-rpc-types-eth", + "alloy-serde", "ethereum_ssz", "ethereum_ssz_derive", + "jsonrpsee-types 0.24.3", "jsonwebtoken", "rand 0.8.5", "serde", @@ -630,35 +501,19 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605fa8462732bb8fd0645a9941e12961e079d45ae6a44634c826f8229c187bdf" -dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-sol-types", - "itertools 0.13.0", - "jsonrpsee-types 0.23.2", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +checksum = "15bb3506ab1cf415d4752778c93e102050399fb8de97b7da405a5bf3e31f5f3b" dependencies = [ - "alloy-consensus 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", + "alloy-consensus", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-serde", "alloy-sol-types", "itertools 0.13.0", + "jsonrpsee-types 0.24.3", "serde", "serde_json", "thiserror", @@ -666,26 +521,26 @@ dependencies = [ [[package]] name = "alloy-rpc-types-mev" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffcb83a5a91d327c40ba2157a19016bb883c1426f1708fea5f9e042032fd73e" +checksum = "19e8cb848b66617f7d58b576bfc416854c4e9ae8d35e14f5077c0c779048f280" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-eips", + "alloy-primitives 0.8.0", + "alloy-serde", "serde", "serde_json", ] [[package]] name = "alloy-rpc-types-trace" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f561a8cdd377b6ac3beab805b9df5ec2c7d99bb6139aab23c317f26df6fb346" +checksum = "16cca915e0aab3b2657b4f9efe02eb88e5483905fb6d244749652aae14e5f92e" dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-primitives 0.8.0", + "alloy-rpc-types-eth", + "alloy-serde", "serde", "serde_json", "thiserror", @@ -693,58 +548,35 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06a4bd39910631c11148c5b2c55e2c61f8626affd2a612e382c668d5e5971ce" +checksum = "68eede4bd722bb872222efbbfbccc8f9b86e597143934b8ce556d3e0487bb662" dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-primitives 0.8.0", + "alloy-rpc-types-eth", + "alloy-serde", "serde", ] [[package]] name = "alloy-serde" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c5b9057acc02aee1b8aac2b5a0729cb0f73d080082c111313e5d1f92a96630" +checksum = "ae417978015f573b4a8c02af17f88558fb22e3fccd12e8a910cf6a2ff331cfcb" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "arbitrary", "serde", "serde_json", ] -[[package]] -name = "alloy-serde" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - [[package]] name = "alloy-signer" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37f10592696f4ab8b687d5a8ab55e998a14ea0ca5f8eb20ad74a96ad671bb54a" +checksum = "b750c9b61ac0646f8f4a61231c2732a337b2c829866fc9a191b96b7eedf80ffe" dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "elliptic-curve 0.13.8", - "k256 0.13.3", - "thiserror", -] - -[[package]] -name = "alloy-signer" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" -dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "async-trait", "auto_impl", "elliptic-curve 0.13.8", @@ -754,13 +586,14 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c640f9343e8f741f837c345c5ea30239ba77938b3691b884c736834853bd16c" dependencies = [ - "alloy-consensus 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-network 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-primitives", - "alloy-signer 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-consensus", + "alloy-network", + "alloy-primitives 0.8.0", + "alloy-signer", "async-trait", "k256 0.13.3", "rand 0.8.5", @@ -769,9 +602,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" +checksum = "183bcfc0f3291d9c41a3774172ee582fb2ce6eb6569085471d8f225de7bb86fc" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -783,9 +616,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" +checksum = "71c4d842beb7a6686d04125603bc57614d5ed78bf95e4753274db3db4ba95214" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -801,9 +634,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" +checksum = "1306e8d3c9e6e6ecf7a39ffaf7291e73a5f655a2defd366ee92c2efebcdf7fee" dependencies = [ "const-hex", "dunce", @@ -816,9 +649,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" +checksum = "f4691da83dce9c9b4c775dd701c87759f173bd3021cbf2e60cde00c5fe6d7241" dependencies = [ "serde", "winnow 0.6.15", @@ -826,11 +659,12 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" +checksum = "577e262966e92112edbd15b1b2c0947cc434d6e8311df96d3329793fe8047da9" dependencies = [ - "alloy-primitives", + "alloy-json-abi", + "alloy-primitives 0.8.0", "alloy-sol-macro", "const-hex", "serde", @@ -838,29 +672,11 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b44b0f6f4a2593b258fa7b6cae8968e6a4c404d9ef4f5bc74401f2d04fa23fa" -dependencies = [ - "alloy-json-rpc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.22.1", - "futures-util", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +checksum = "2799749ca692ae145f54968778877afd7c95e788488f176cfdfcf2a8abeb2062" dependencies = [ - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-json-rpc", "base64 0.22.1", "futures-util", "futures-utils-wasm", @@ -875,26 +691,12 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8f1eefa8cb9e7550740ee330feba4fed303a77ad3085707546f9152a88c380" -dependencies = [ - "alloy-json-rpc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.12.5", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-http" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +checksum = "bc10c4dd932f66e0db6cc5735241e0c17a6a18564b430bbc1839f7db18587a93" dependencies = [ - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-json-rpc", + "alloy-transport", "reqwest 0.12.5", "serde_json", "tower", @@ -904,12 +706,13 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.2.0" -source = "git+https://github.com/alloy-rs/alloy?rev=f2d80032#f2d80032056e715a283be08c84063abf1b47957f" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f39f88798c3282914079a3eda3ea8b9fbf21e383a0ce85958b4f1c170d222f" dependencies = [ - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-pubsub 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-json-rpc", + "alloy-pubsub", + "alloy-transport", "bytes", "futures", "interprocess", @@ -922,12 +725,12 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ccc1c8f8ae415e93ec0e7851bd4cdf4afdd48793d13a91b860317da1f36104" +checksum = "65e732028930aa17b7edd464a9711365417635e984028fcc7176393ccea22c00" dependencies = [ - "alloy-pubsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-transport 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-pubsub", + "alloy-transport", "futures", "http 1.1.0", "rustls 0.23.12", @@ -940,15 +743,19 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03704f265cbbb943b117ecb5055fd46e8f41e7dc8a58b1aed20bcd40ace38c15" +checksum = "398a977d774db13446b8cead8cfa9517aebf9e03fc8a1512892dc1e03e70bb04" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-rlp", - "derive_more", + "arbitrary", + "derive_arbitrary", + "derive_more 1.0.0", "hashbrown 0.14.5", "nybbles", + "proptest", + "proptest-derive", "serde", "smallvec", "tracing", @@ -1631,19 +1438,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bls12_381" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" -dependencies = [ - "ff 0.13.0", - "group 0.13.0", - "pairing", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "blst" version = "0.3.13" @@ -1656,144 +1450,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "boa_ast" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49637e7ecb7c541c46c3e885d4c49326ad8076dbfb88bef2cf3165d8ea7df2b" -dependencies = [ - "bitflags 2.6.0", - "boa_interner", - "boa_macros", - "indexmap 2.2.6", - "num-bigint", - "rustc-hash 2.0.0", -] - -[[package]] -name = "boa_engine" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411558b4cbc7d0303012e26721815e612fed78179313888fd5dd8d6c50d70099" -dependencies = [ - "arrayvec", - "bitflags 2.6.0", - "boa_ast", - "boa_gc", - "boa_interner", - "boa_macros", - "boa_parser", - "boa_profiler", - "boa_string", - "bytemuck", - "cfg-if", - "dashmap", - "fast-float", - "hashbrown 0.14.5", - "icu_normalizer", - "indexmap 2.2.6", - "intrusive-collections", - "itertools 0.13.0", - "num-bigint", - "num-integer", - "num-traits", - "num_enum", - "once_cell", - "pollster", - "portable-atomic", - "rand 0.8.5", - "regress", - "rustc-hash 2.0.0", - "ryu-js", - "serde", - "serde_json", - "sptr", - "static_assertions", - "tap", - "thin-vec", - "thiserror", - "time", -] - -[[package]] -name = "boa_gc" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eff345a85a39cf9b8ed863198947d61e6df2b1d774002b57341158b0ce2c525" -dependencies = [ - "boa_macros", - "boa_profiler", - "boa_string", - "hashbrown 0.14.5", - "thin-vec", -] - -[[package]] -name = "boa_interner" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b779280420804c70da9043d152c84eb96e2f7c9e7d1ec3262decf59f9349df" -dependencies = [ - "boa_gc", - "boa_macros", - "hashbrown 0.14.5", - "indexmap 2.2.6", - "once_cell", - "phf 0.11.2", - "rustc-hash 2.0.0", - "static_assertions", -] - -[[package]] -name = "boa_macros" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e0097fa69cde4c95f9869654004340fbbe2bcf3ce9189ba2a31a65ac40e0a1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", - "synstructure 0.13.1", -] - -[[package]] -name = "boa_parser" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd63fe8faf62561fc8c50f9402687e8cfde720b57d292fb3b4ac17c821878ac1" -dependencies = [ - "bitflags 2.6.0", - "boa_ast", - "boa_interner", - "boa_macros", - "boa_profiler", - "fast-float", - "icu_properties", - "num-bigint", - "num-traits", - "regress", - "rustc-hash 2.0.0", -] - -[[package]] -name = "boa_profiler" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9da895f0df9e2a97b36c1f98e0c5d2ab963abc8679d80f2a66f7bcb211ce90" - -[[package]] -name = "boa_string" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9ca6668df83fcd3c2903f6f296b7180421908c5b478ebe0d1c468be9fd60e1c" -dependencies = [ - "fast-float", - "paste", - "rustc-hash 2.0.0", - "sptr", - "static_assertions", -] - [[package]] name = "boyer-moore-magiclen" version = "0.2.20" @@ -1951,15 +1607,16 @@ dependencies = [ [[package]] name = "c-kzg" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" dependencies = [ "blst", "cc", "glob", "hex", "libc", + "once_cell", "serde", ] @@ -2089,15 +1746,6 @@ dependencies = [ "half", ] -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - [[package]] name = "cipher" version = "0.4.4" @@ -2138,7 +1786,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -2211,23 +1859,11 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "confy" -version = "0.6.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45b1f4c00870f07dc34adcac82bb6a72cc5aabca8536ba1797e01df51d2ce9a0" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "directories", - "serde", - "thiserror", - "toml 0.8.15", + "crossbeam-utils", ] [[package]] @@ -2505,6 +2141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] @@ -2572,31 +2209,13 @@ dependencies = [ "syn 2.0.72", ] -[[package]] -name = "ctr" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481" -dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher 0.3.0", -] - [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher 0.4.4", + "cipher", ] [[package]] @@ -2640,38 +2259,14 @@ dependencies = [ "syn 2.0.72", ] -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -2684,28 +2279,17 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", + "strsim", "syn 2.0.72", ] -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - [[package]] name = "darling_macro" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.10", + "darling_core", "quote", "syn 2.0.72", ] @@ -2723,6 +2307,20 @@ dependencies = [ "parking_lot_core 0.9.10", ] +[[package]] +name = "dashmap" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -2831,6 +2429,28 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.72", + "unicode-xid", +] + [[package]] name = "digest" version = "0.9.0" @@ -2852,15 +2472,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "directories" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs" version = "5.0.1" @@ -2905,14 +2516,15 @@ dependencies = [ [[package]] name = "discv5" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cafb8ed8d460b7d1c8d4c970270d45ecb5e283179a3945143196624c55cda6ac" +checksum = "f569b8c367554666c8652305621e8bae3634a2ff5c6378081d5bd8c399c99f23" dependencies = [ - "aes 0.7.5", + "aes", "aes-gcm", "alloy-rlp", "arrayvec", + "ctr", "delay_map", "enr 0.12.1", "fnv", @@ -2921,9 +2533,10 @@ dependencies = [ "hex", "hkdf", "lazy_static", - "libp2p", + "libp2p-identity", "lru", "more-asserts", + "multiaddr 0.18.1", "parking_lot 0.11.2", "rand 0.8.5", "smallvec", @@ -2934,17 +2547,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - [[package]] name = "doctest-file" version = "1.0.0" @@ -3271,7 +2873,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "serde_yaml 0.8.26", + "serde_yaml", "sha2 0.10.8", "ssz_rs 0.9.0 (git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72)", "thiserror", @@ -3297,25 +2899,25 @@ dependencies = [ [[package]] name = "ethereum_ssz" -version = "0.5.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425" +checksum = "1e999563461faea0ab9bc0024e5e66adcee35881f3d5062f52f31a4070fe1522" dependencies = [ - "ethereum-types", - "itertools 0.10.5", + "alloy-primitives 0.8.0", + "itertools 0.13.0", "smallvec", ] [[package]] name = "ethereum_ssz_derive" -version = "0.5.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eccd5378ec34a07edd3d9b48088cbc63309d0367d14ba10b0cdb1d1791080ea" +checksum = "f3deae99c8e74829a00ba7a92d49055732b3c1f093f2ccfa3cbc621679b6fa91" dependencies = [ - "darling 0.13.4", + "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.72", ] [[package]] @@ -3440,7 +3042,6 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "bitvec", "rand_core 0.6.4", "subtle", ] @@ -3457,7 +3058,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "arbitrary", "byteorder", "rand 0.8.5", "rustc-hex", @@ -3584,7 +3184,6 @@ dependencies = [ "futures-core", "futures-task", "futures-util", - "num_cpus", ] [[package]] @@ -3731,9 +3330,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -3787,15 +3386,15 @@ dependencies = [ [[package]] name = "gloo-net" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43aaa242d1239a8822c15c645f02166398da4f8b5c4bae795c1f5b44e9eee173" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" dependencies = [ "futures-channel", "futures-core", "futures-sink", "gloo-utils", - "http 0.2.12", + "http 1.1.0", "js-sys", "pin-project", "serde", @@ -3838,7 +3437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" dependencies = [ "cfg-if", - "dashmap", + "dashmap 5.5.3", "futures", "futures-timer", "no-std-compat", @@ -3921,6 +3520,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + [[package]] name = "hash_hasher" version = "2.0.3" @@ -4292,6 +3897,7 @@ dependencies = [ "hyper-util", "log", "rustls 0.23.12", + "rustls-native-certs 0.7.1", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -4371,124 +3977,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -4668,15 +4156,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "intrusive-collections" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b694dc9f70c3bda874626d2aed13b780f137aab435f4e9814121955cf706122e" -dependencies = [ - "memoffset", -] - [[package]] name = "ipconfig" version = "0.3.2" @@ -4822,18 +4301,18 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b089779ad7f80768693755a031cc14a7766aba707cbe886674e3f79e9b7e47" -dependencies = [ - "jsonrpsee-client-transport 0.23.2", - "jsonrpsee-core 0.23.2", - "jsonrpsee-http-client 0.23.2", - "jsonrpsee-proc-macros 0.23.2", - "jsonrpsee-server 0.23.2", - "jsonrpsee-types 0.23.2", - "jsonrpsee-wasm-client 0.23.2", - "jsonrpsee-ws-client 0.23.2", +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec465b607a36dc5dd45d48b7689bc83f679f66a3ac6b6b21cc787a11e0f8685" +dependencies = [ + "jsonrpsee-client-transport 0.24.3", + "jsonrpsee-core 0.24.3", + "jsonrpsee-http-client 0.24.3", + "jsonrpsee-proc-macros 0.24.3", + "jsonrpsee-server 0.24.3", + "jsonrpsee-types 0.24.3", + "jsonrpsee-wasm-client 0.24.3", + "jsonrpsee-ws-client 0.24.3", "tokio", "tracing", ] @@ -4863,16 +4342,16 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08163edd8bcc466c33d79e10f695cdc98c00d1e6ddfb95cec41b6b0279dd5432" +checksum = "90f0977f9c15694371b8024c35ab58ca043dbbf4b51ccb03db8858a021241df1" dependencies = [ "base64 0.22.1", "futures-channel", "futures-util", - "gloo-net 0.5.0", + "gloo-net 0.6.0", "http 1.1.0", - "jsonrpsee-core 0.23.2", + "jsonrpsee-core 0.24.3", "pin-project", "rustls 0.23.12", "rustls-pki-types", @@ -4914,24 +4393,22 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79712302e737d23ca0daa178e752c9334846b08321d439fd89af9a384f8c830b" +checksum = "e942c55635fbf5dc421938b8558a8141c7e773720640f4f1dbe1f4164ca4e221" dependencies = [ - "anyhow", "async-trait", - "beef", "bytes", "futures-timer", "futures-util", "http 1.1.0", "http-body 1.0.1", "http-body-util", - "jsonrpsee-types 0.23.2", + "jsonrpsee-types 0.24.3", "parking_lot 0.12.3", "pin-project", "rand 0.8.5", - "rustc-hash 1.1.0", + "rustc-hash 2.0.0", "serde", "serde_json", "thiserror", @@ -4963,9 +4440,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d90064e04fb9d7282b1c71044ea94d0bbc6eff5621c66f1a0bce9e9de7cf3ac" +checksum = "e33774602df12b68a2310b38a535733c477ca4a498751739f89fe8dbbb62ec4c" dependencies = [ "async-trait", "base64 0.22.1", @@ -4973,8 +4450,8 @@ dependencies = [ "hyper 1.4.1", "hyper-rustls 0.27.2", "hyper-util", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", "rustls 0.23.12", "rustls-platform-verifier", "serde", @@ -5001,9 +4478,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7895f186d5921065d96e16bd795e5ca89ac8356ec423fafc6e3d7cf8ec11aee4" +checksum = "6b07a2daf52077ab1b197aea69a5c990c060143835bf04c77070e98903791715" dependencies = [ "heck 0.5.0", "proc-macro-crate 3.1.0", @@ -5037,19 +4514,18 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "654afab2e92e5d88ebd8a39d6074483f3f2bfdf91c5ac57fe285e7127cdd4f51" +checksum = "038fb697a709bec7134e9ccbdbecfea0e2d15183f7140254afef7c5610a3f488" dependencies = [ - "anyhow", "futures-util", "http 1.1.0", "http-body 1.0.1", "http-body-util", "hyper 1.4.1", "hyper-util", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", "pin-project", "route-recognizer", "serde", @@ -5079,11 +4555,10 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c465fbe385238e861fdc4d1c85e04ada6c1fd246161d26385c1b311724d2af" +checksum = "23b67d6e008164f027afbc2e7bb79662650158d26df200040282d2aa1cbb093b" dependencies = [ - "beef", "http 1.1.0", "serde", "serde_json", @@ -5103,13 +4578,13 @@ dependencies = [ [[package]] name = "jsonrpsee-wasm-client" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4727ac037f834c6f04c0912cada7532dbddb54e92fbc64e33d6cb8c24af313c9" +checksum = "0470d0ae043ffcb0cd323797a631e637fb4b55fe3eaa6002934819458bba62a7" dependencies = [ - "jsonrpsee-client-transport 0.23.2", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "jsonrpsee-client-transport 0.24.3", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", ] [[package]] @@ -5127,14 +4602,14 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.23.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c28759775f5cb2f1ea9667672d3fe2b0e701d1f4b7b67954e60afe7fd058b5e" +checksum = "992bf67d1132f88edf4a4f8cff474cf01abb2be203004a2b8e11c2b20795b99e" dependencies = [ "http 1.1.0", - "jsonrpsee-client-transport 0.23.2", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "jsonrpsee-client-transport 0.24.3", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", "url", ] @@ -5213,21 +4688,6 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" -[[package]] -name = "kzg-rs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9920cd4460ce3cbca19c62f3bb9a9611562478a4dc9d2c556f4a7d049c5b6b" -dependencies = [ - "bls12_381", - "glob", - "hex", - "once_cell", - "serde", - "serde_derive", - "serde_yaml 0.9.34+deprecated", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -5328,102 +4788,27 @@ version = "0.17.0+1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libloading" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "libp2p" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681fb3f183edfbedd7a57d32ebe5dcdc0b9f94061185acf3c30249349cc6fc99" -dependencies = [ - "bytes", - "either", - "futures", - "futures-timer", - "getrandom 0.2.15", - "instant", - "libp2p-allow-block-list", - "libp2p-connection-limits", - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "multiaddr 0.18.1", - "pin-project", - "rw-stream-sink", - "thiserror", -] - -[[package]] -name = "libp2p-allow-block-list" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "107b238b794cb83ab53b74ad5dcf7cca3200899b72fe662840cfb52f5b0a32e6" -dependencies = [ - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "void", + "cc", + "libc", + "libz-sys", + "pkg-config", ] [[package]] -name = "libp2p-connection-limits" -version = "0.3.1" +name = "libloading" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cd50a78ccfada14de94cbacd3ce4b0138157f376870f13d3a8422cd075b4fd" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "void", + "cfg-if", + "windows-targets 0.52.6", ] [[package]] -name = "libp2p-core" -version = "0.41.3" +name = "libm" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5a8920cbd8540059a01950c1e5c96ea8d89eb50c51cd366fc18bdf540a6e48f" -dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "libp2p-identity", - "multiaddr 0.18.1", - "multihash 0.19.1", - "multistream-select", - "once_cell", - "parking_lot 0.12.3", - "pin-project", - "quick-protobuf", - "rand 0.8.5", - "rw-stream-sink", - "smallvec", - "thiserror", - "tracing", - "unsigned-varint 0.8.0", - "void", - "web-time", -] +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libp2p-identity" @@ -5438,35 +4823,12 @@ dependencies = [ "libsecp256k1", "multihash 0.19.1", "quick-protobuf", - "rand 0.8.5", "sha2 0.10.8", "thiserror", "tracing", "zeroize", ] -[[package]] -name = "libp2p-swarm" -version = "0.44.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80cae6cb75f89dbca53862f9ebe0b9f463aa7b302762fcfaafb9e51dcc9b0f7e" -dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-identity", - "lru", - "multistream-select", - "once_cell", - "rand 0.8.5", - "smallvec", - "tracing", - "void", -] - [[package]] name = "libproc" version = "0.14.8" @@ -5580,12 +4942,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "lock_api" version = "0.4.12" @@ -5727,15 +5083,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "mempool-dumpster" version = "0.1.1" @@ -5984,7 +5331,7 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint 0.7.2", + "unsigned-varint", "url", ] @@ -6003,7 +5350,7 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint 0.7.2", + "unsigned-varint", "url", ] @@ -6028,7 +5375,7 @@ dependencies = [ "digest 0.10.7", "multihash-derive", "sha2 0.10.8", - "unsigned-varint 0.7.2", + "unsigned-varint", ] [[package]] @@ -6038,7 +5385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" dependencies = [ "core2", - "unsigned-varint 0.7.2", + "unsigned-varint", ] [[package]] @@ -6052,21 +5399,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", -] - -[[package]] -name = "multistream-select" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" -dependencies = [ - "bytes", - "futures", - "log", - "pin-project", - "smallvec", - "unsigned-varint 0.7.2", + "synstructure", ] [[package]] @@ -6204,7 +5537,6 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "serde", ] [[package]] @@ -6333,6 +5665,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" dependencies = [ "alloy-rlp", + "arbitrary", "const-hex", "proptest", "serde", @@ -6360,6 +5693,64 @@ version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +[[package]] +name = "op-alloy-consensus" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3041068147bb9abce8973644991e11c075fa8a7931a272bc8eb935971a2d03d7" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives 0.8.0", + "alloy-rlp", + "alloy-serde", + "derive_more 1.0.0", + "serde", + "spin", +] + +[[package]] +name = "op-alloy-network" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf926fccb35a1ad784cf8c2771a3a7b2c891379fcc78bc7cdc23dec1b57a6459" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", + "alloy-primitives 0.8.0", + "alloy-rpc-types-eth", + "op-alloy-consensus", + "op-alloy-rpc-types", +] + +[[package]] +name = "op-alloy-rpc-types" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f57a192b16bd94296637616908a5701d4318d6c2c5119c93a1df5442ec97c13" +dependencies = [ + "alloy-network", + "alloy-primitives 0.8.0", + "alloy-rpc-types-eth", + "alloy-serde", + "op-alloy-consensus", + "serde", + "serde_json", +] + +[[package]] +name = "op-alloy-rpc-types-engine" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea246be3da604d2f68e86cc510cf05219db0ed24273ebd59d86065971ba0e3f" +dependencies = [ + "alloy-primitives 0.8.0", + "alloy-rpc-types-engine", + "alloy-serde", + "serde", +] + [[package]] name = "opaque-debug" version = "0.3.1" @@ -6466,15 +5857,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "pairing" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" -dependencies = [ - "group 0.13.0", -] - [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -6821,6 +6203,15 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "plain_hasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e19e6491bdde87c2c43d70f4c194bc8a758f2eb732df00f61e43f7362e3b4cc" +dependencies = [ + "crunchy", +] + [[package]] name = "planus" version = "0.3.1" @@ -7107,17 +6498,11 @@ dependencies = [ "version_check", ] -[[package]] -name = "pollster" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" - [[package]] name = "polyval" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -7323,17 +6708,6 @@ dependencies = [ "proptest", ] -[[package]] -name = "proptest-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "proptest-derive" version = "0.5.0" @@ -7598,23 +6972,23 @@ version = "0.1.0" dependencies = [ "ahash", "alloy-chains", - "alloy-consensus 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-eips 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-json-rpc 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-network 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", "alloy-node-bindings", - "alloy-primitives", - "alloy-provider 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-pubsub 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-primitives 0.8.0", + "alloy-provider", + "alloy-pubsub", "alloy-rlp", - "alloy-rpc-types 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-rpc-types-beacon 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-rpc-types-engine 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-rpc-types-eth 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-serde 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-rpc-types", + "alloy-rpc-types-beacon", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-serde", "alloy-signer-local", - "alloy-transport 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", - "alloy-transport-http 0.2.0 (git+https://github.com/alloy-rs/alloy?rev=f2d80032)", + "alloy-transport", + "alloy-transport-http", "async-trait", "atoi", "beacon-api-client", @@ -7803,16 +7177,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "regress" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16fe0a24af5daaae947294213d2fd2646fbf5e1fbacc1d4ba3e84b2393854842" -dependencies = [ - "hashbrown 0.14.5", - "memchr", -] - [[package]] name = "reqwest" version = "0.11.27" @@ -7882,6 +7246,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls 0.23.12", + "rustls-native-certs 0.7.1", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", @@ -7912,14 +7277,13 @@ dependencies = [ [[package]] name = "reth" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "aquamarine", "backon", "clap", - "confy", "discv5", "eyre", "fdlimit", @@ -7956,7 +7320,9 @@ dependencies = [ "reth-node-core", "reth-node-ethereum", "reth-node-events", + "reth-node-metrics", "reth-optimism-primitives", + "reth-optimism-rpc", "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", @@ -7979,6 +7345,7 @@ dependencies = [ "reth-tracing", "reth-transaction-pool", "reth-trie", + "reth-trie-db", "serde", "serde_json", "similar-asserts", @@ -7991,8 +7358,8 @@ dependencies = [ [[package]] name = "reth-auto-seal-consensus" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "futures-util", "reth-beacon-consensus", @@ -8011,6 +7378,7 @@ dependencies = [ "reth-stages-api", "reth-tokio-util", "reth-transaction-pool", + "reth-trie", "tokio", "tokio-stream", "tracing", @@ -8018,8 +7386,8 @@ dependencies = [ [[package]] name = "reth-basic-payload-builder" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "futures-core", @@ -8041,8 +7409,8 @@ dependencies = [ [[package]] name = "reth-beacon-consensus" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "futures", "itertools 0.13.0", @@ -8075,8 +7443,8 @@ dependencies = [ [[package]] name = "reth-blockchain-tree" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "aquamarine", "linked_hash_set", @@ -8098,6 +7466,7 @@ dependencies = [ "reth-stages-api", "reth-storage-errors", "reth-trie", + "reth-trie-db", "reth-trie-parallel", "tokio", "tracing", @@ -8105,8 +7474,8 @@ dependencies = [ [[package]] name = "reth-blockchain-tree-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-consensus", "reth-execution-errors", @@ -8115,17 +7484,44 @@ dependencies = [ "thiserror", ] +[[package]] +name = "reth-chain-state" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "alloy-signer", + "alloy-signer-local", + "auto_impl", + "derive_more 1.0.0", + "metrics", + "parking_lot 0.12.3", + "pin-project", + "rand 0.8.5", + "reth-chainspec", + "reth-errors", + "reth-execution-types", + "reth-metrics", + "reth-primitives", + "reth-storage-api", + "reth-trie", + "revm", + "tokio", + "tokio-stream", + "tracing", +] + [[package]] name = "reth-chainspec" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-chains", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-eips", + "alloy-genesis", + "alloy-primitives 0.8.0", "alloy-trie", - "derive_more", + "auto_impl", + "derive_more 1.0.0", "once_cell", "reth-ethereum-forks", "reth-network-peers", @@ -8136,21 +7532,19 @@ dependencies = [ [[package]] name = "reth-cli-commands" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "ahash", "backon", "clap", "comfy-table", - "confy", "crossterm", "eyre", "fdlimit", "futures", "human_bytes", "itertools 0.13.0", - "metrics-process", "ratatui", "reth-beacon-consensus", "reth-chainspec", @@ -8162,14 +7556,18 @@ dependencies = [ "reth-db-api", "reth-db-common", "reth-downloaders", + "reth-ecies", + "reth-eth-wire", "reth-evm", "reth-exex", "reth-fs-util", "reth-network", "reth-network-p2p", + "reth-network-peers", "reth-node-builder", "reth-node-core", "reth-node-events", + "reth-node-metrics", "reth-primitives", "reth-provider", "reth-prune", @@ -8177,6 +7575,8 @@ dependencies = [ "reth-static-file", "reth-static-file-types", "reth-trie", + "reth-trie-db", + "secp256k1", "serde", "serde_json", "tokio", @@ -8186,8 +7586,8 @@ dependencies = [ [[package]] name = "reth-cli-runner" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-tasks", "tokio", @@ -8196,11 +7596,11 @@ dependencies = [ [[package]] name = "reth-cli-util" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-eips", + "alloy-primitives 0.8.0", "eyre", "libc", "rand 0.8.5", @@ -8211,13 +7611,13 @@ dependencies = [ [[package]] name = "reth-codecs" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives 0.8.0", "alloy-trie", "bytes", "modular-bitfield", @@ -8227,8 +7627,8 @@ dependencies = [ [[package]] name = "reth-codecs-derive" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "convert_case 0.6.0", "proc-macro2", @@ -8238,31 +7638,32 @@ dependencies = [ [[package]] name = "reth-config" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "confy", + "eyre", "humantime-serde", "reth-network-types", "reth-prune-types", "reth-stages-types", "serde", + "toml 0.8.15", ] [[package]] name = "reth-consensus" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "auto_impl", + "derive_more 1.0.0", "reth-primitives", - "thiserror-no-std", ] [[package]] name = "reth-consensus-common" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-chainspec", "reth-consensus", @@ -8271,12 +7672,12 @@ dependencies = [ [[package]] name = "reth-consensus-debug-client" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-provider 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-consensus", + "alloy-eips", + "alloy-provider", "auto_impl", "eyre", "futures", @@ -8294,11 +7695,11 @@ dependencies = [ [[package]] name = "reth-db" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "bytes", - "derive_more", + "derive_more 1.0.0", "eyre", "metrics", "page_size", @@ -8325,17 +7726,18 @@ dependencies = [ [[package]] name = "reth-db-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "arbitrary", "bytes", - "derive_more", + "derive_more 1.0.0", "metrics", "modular-bitfield", "parity-scale-codec", "proptest", "reth-codecs", + "reth-db-models", "reth-primitives", "reth-primitives-traits", "reth-prune-types", @@ -8347,10 +7749,10 @@ dependencies = [ [[package]] name = "reth-db-common" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-genesis", "boyer-moore-magiclen", "eyre", "reth-chainspec", @@ -8364,18 +7766,33 @@ dependencies = [ "reth-provider", "reth-stages-types", "reth-trie", + "reth-trie-db", "serde", "serde_json", "thiserror", "tracing", ] +[[package]] +name = "reth-db-models" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "arbitrary", + "bytes", + "modular-bitfield", + "proptest", + "reth-codecs", + "reth-primitives", + "serde", +] + [[package]] name = "reth-discv4" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-rlp", "discv5", "enr 0.12.1", @@ -8396,19 +7813,17 @@ dependencies = [ [[package]] name = "reth-discv5" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-rlp", - "derive_more", + "derive_more 1.0.0", "discv5", "enr 0.12.1", "futures", "itertools 0.13.0", - "libp2p-identity", "metrics", - "multiaddr 0.18.1", "rand 0.8.5", "reth-chainspec", "reth-ethereum-forks", @@ -8422,10 +7837,10 @@ dependencies = [ [[package]] name = "reth-dns-discovery" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "data-encoding", "enr 0.12.1", "linked_hash_set", @@ -8444,8 +7859,8 @@ dependencies = [ [[package]] name = "reth-downloaders" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "futures", @@ -8471,17 +7886,17 @@ dependencies = [ [[package]] name = "reth-ecies" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "aes 0.8.4", - "alloy-primitives", + "aes", + "alloy-primitives 0.8.0", "alloy-rlp", "block-padding", "byteorder", - "cipher 0.4.4", + "cipher", "concat-kdf", - "ctr 0.9.2", + "ctr", "digest 0.10.7", "futures", "generic-array", @@ -8502,33 +7917,54 @@ dependencies = [ [[package]] name = "reth-engine-primitives" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-chainspec", "reth-payload-primitives", "serde", ] +[[package]] +name = "reth-engine-service" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "futures", + "pin-project", + "reth-beacon-consensus", + "reth-chainspec", + "reth-consensus", + "reth-db-api", + "reth-engine-primitives", + "reth-engine-tree", + "reth-evm", + "reth-network-p2p", + "reth-payload-builder", + "reth-payload-validator", + "reth-provider", + "reth-prune", + "reth-stages-api", + "reth-tasks", + "thiserror", +] + [[package]] name = "reth-engine-tree" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "aquamarine", "futures", "metrics", - "parking_lot 0.12.3", "reth-beacon-consensus", "reth-blockchain-tree", "reth-blockchain-tree-api", - "reth-chainspec", + "reth-chain-state", "reth-consensus", "reth-db", "reth-db-api", "reth-engine-primitives", "reth-errors", - "reth-ethereum-consensus", "reth-evm", "reth-metrics", "reth-network-p2p", @@ -8538,44 +7974,50 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-prune", - "reth-prune-types", "reth-revm", "reth-rpc-types", "reth-stages-api", - "reth-stages-types", - "reth-static-file", "reth-tasks", - "reth-tokio-util", "reth-trie", - "revm", + "thiserror", "tokio", - "tokio-stream", "tracing", ] [[package]] name = "reth-engine-util" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "eyre", "futures", + "itertools 0.13.0", "pin-project", "reth-beacon-consensus", "reth-engine-primitives", + "reth-errors", + "reth-ethereum-forks", + "reth-evm", "reth-fs-util", - "reth-rpc", + "reth-payload-validator", + "reth-primitives", + "reth-provider", + "reth-revm", "reth-rpc-types", + "reth-rpc-types-compat", + "reth-trie", + "revm-primitives", "serde", "serde_json", + "tokio", "tokio-util", "tracing", ] [[package]] name = "reth-errors" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-blockchain-tree-api", "reth-consensus", @@ -8587,12 +8029,12 @@ dependencies = [ [[package]] name = "reth-eth-wire" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "bytes", - "derive_more", + "derive_more 1.0.0", "futures", "pin-project", "reth-chainspec", @@ -8612,14 +8054,14 @@ dependencies = [ [[package]] name = "reth-eth-wire-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-chains", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-genesis", "alloy-rlp", "bytes", - "derive_more", + "derive_more 1.0.0", "reth-chainspec", "reth-codecs-derive", "reth-primitives", @@ -8628,8 +8070,8 @@ dependencies = [ [[package]] name = "reth-ethereum-consensus" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-chainspec", "reth-consensus", @@ -8638,30 +8080,10 @@ dependencies = [ "tracing", ] -[[package]] -name = "reth-ethereum-engine" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" -dependencies = [ - "futures", - "pin-project", - "reth-beacon-consensus", - "reth-chainspec", - "reth-db-api", - "reth-engine-tree", - "reth-ethereum-engine-primitives", - "reth-network-p2p", - "reth-stages-api", - "reth-tasks", - "thiserror", - "tokio", - "tokio-stream", -] - [[package]] name = "reth-ethereum-engine-primitives" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "reth-chainspec", @@ -8678,11 +8100,11 @@ dependencies = [ [[package]] name = "reth-ethereum-forks" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-chains", - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-rlp", "arbitrary", "auto_impl", @@ -8690,7 +8112,7 @@ dependencies = [ "dyn-clone", "once_cell", "proptest", - "proptest-derive 0.5.0", + "proptest-derive", "rustc-hash 2.0.0", "serde", "thiserror-no-std", @@ -8698,8 +8120,8 @@ dependencies = [ [[package]] name = "reth-ethereum-payload-builder" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-basic-payload-builder", "reth-errors", @@ -8711,14 +8133,15 @@ dependencies = [ "reth-provider", "reth-revm", "reth-transaction-pool", + "reth-trie", "revm", "tracing", ] [[package]] name = "reth-etl" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "rayon", "reth-db-api", @@ -8727,10 +8150,10 @@ dependencies = [ [[package]] name = "reth-evm" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-eips", "auto_impl", "futures-util", "reth-chainspec", @@ -8745,10 +8168,10 @@ dependencies = [ [[package]] name = "reth-evm-ethereum" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-eips", "alloy-sol-types", "reth-chainspec", "reth-ethereum-consensus", @@ -8761,24 +8184,46 @@ dependencies = [ "revm-primitives", ] +[[package]] +name = "reth-evm-optimism" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "reth-chainspec", + "reth-ethereum-forks", + "reth-evm", + "reth-execution-errors", + "reth-execution-types", + "reth-optimism-consensus", + "reth-primitives", + "reth-prune-types", + "reth-revm", + "revm", + "revm-primitives", + "thiserror", + "tracing", +] + [[package]] name = "reth-execution-errors" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-eips", + "alloy-primitives 0.8.0", + "alloy-rlp", + "derive_more 1.0.0", + "nybbles", "reth-consensus", "reth-prune-types", "reth-storage-errors", "revm-primitives", - "thiserror-no-std", ] [[package]] name = "reth-execution-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-execution-errors", "reth-primitives", @@ -8788,8 +8233,8 @@ dependencies = [ [[package]] name = "reth-exex" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "eyre", "futures", @@ -8798,7 +8243,6 @@ dependencies = [ "reth-evm", "reth-exex-types", "reth-metrics", - "reth-network", "reth-node-api", "reth-node-core", "reth-payload-builder", @@ -8816,17 +8260,17 @@ dependencies = [ [[package]] name = "reth-exex-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "reth-provider", ] [[package]] name = "reth-fs-util" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "serde", "serde_json", @@ -8835,15 +8279,15 @@ dependencies = [ [[package]] name = "reth-ipc" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "async-trait", "bytes", "futures", "futures-util", "interprocess", - "jsonrpsee 0.23.2", + "jsonrpsee 0.24.3", "pin-project", "serde_json", "thiserror", @@ -8856,13 +8300,13 @@ dependencies = [ [[package]] name = "reth-libmdbx" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "bitflags 2.6.0", "byteorder", - "dashmap", - "derive_more", + "dashmap 6.0.1", + "derive_more 1.0.0", "indexmap 2.2.6", "parking_lot 0.12.3", "reth-mdbx-sys", @@ -8872,8 +8316,8 @@ dependencies = [ [[package]] name = "reth-mdbx-sys" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "bindgen", "cc", @@ -8881,8 +8325,8 @@ dependencies = [ [[package]] name = "reth-metrics" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "futures", "metrics", @@ -8893,10 +8337,9 @@ dependencies = [ [[package]] name = "reth-metrics-derive" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "once_cell", "proc-macro2", "quote", "regex", @@ -8905,16 +8348,16 @@ dependencies = [ [[package]] name = "reth-net-banlist" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", ] [[package]] name = "reth-net-nat" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "futures-util", "reqwest 0.12.5", @@ -8925,17 +8368,16 @@ dependencies = [ [[package]] name = "reth-network" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "aquamarine", "auto_impl", - "derive_more", + "derive_more 1.0.0", "discv5", "enr 0.12.1", "futures", - "humantime-serde", "itertools 0.13.0", "metrics", "parking_lot 0.12.3", @@ -8964,7 +8406,6 @@ dependencies = [ "schnellru", "secp256k1", "serde", - "serde_json", "smallvec", "thiserror", "tokio", @@ -8975,43 +8416,51 @@ dependencies = [ [[package]] name = "reth-network-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-rpc-types-admin", + "auto_impl", + "derive_more 1.0.0", "enr 0.12.1", - "reth-eth-wire", + "futures", + "reth-eth-wire-types", + "reth-ethereum-forks", + "reth-network-p2p", "reth-network-peers", + "reth-network-types", + "reth-tokio-util", "serde", "thiserror", "tokio", + "tokio-stream", ] [[package]] name = "reth-network-p2p" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "auto_impl", + "derive_more 1.0.0", "futures", "reth-consensus", "reth-eth-wire-types", - "reth-network-api", "reth-network-peers", + "reth-network-types", "reth-primitives", "reth-storage-errors", - "thiserror", "tokio", "tracing", ] [[package]] name = "reth-network-peers" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "alloy-rlp", "enr 0.12.1", "secp256k1", @@ -9023,12 +8472,12 @@ dependencies = [ [[package]] name = "reth-network-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "humantime-serde", + "reth-ethereum-forks", "reth-net-banlist", - "reth-network-api", "reth-network-peers", "serde", "serde_json", @@ -9037,13 +8486,13 @@ dependencies = [ [[package]] name = "reth-nippy-jar" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "anyhow", "bincode", "cuckoofilter", - "derive_more", + "derive_more 1.0.0", "lz4_flex", "memmap2 0.9.4", "ph", @@ -9057,28 +8506,29 @@ dependencies = [ [[package]] name = "reth-node-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ + "reth-chainspec", "reth-db-api", "reth-engine-primitives", "reth-evm", - "reth-network", + "reth-network-api", "reth-payload-builder", "reth-payload-primitives", "reth-provider", + "reth-rpc-eth-api", "reth-tasks", "reth-transaction-pool", ] [[package]] name = "reth-node-builder" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ + "alloy-network", "aquamarine", - "backon", - "confy", "eyre", "fdlimit", "futures", @@ -9094,15 +8544,20 @@ dependencies = [ "reth-db-api", "reth-db-common", "reth-downloaders", + "reth-engine-service", + "reth-engine-tree", "reth-engine-util", "reth-evm", "reth-exex", "reth-network", + "reth-network-api", "reth-network-p2p", "reth-node-api", "reth-node-core", "reth-node-events", + "reth-node-metrics", "reth-payload-builder", + "reth-payload-validator", "reth-primitives", "reth-provider", "reth-prune", @@ -9115,6 +8570,7 @@ dependencies = [ "reth-stages", "reth-static-file", "reth-tasks", + "reth-tokio-util", "reth-tracing", "reth-transaction-pool", "secp256k1", @@ -9125,26 +8581,18 @@ dependencies = [ [[package]] name = "reth-node-core" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-genesis", + "alloy-rpc-types-engine", "clap", "const_format", - "derive_more", + "derive_more 1.0.0", "dirs-next", "eyre", "futures", - "http 1.1.0", "humantime", - "jsonrpsee 0.23.2", - "metrics", - "metrics-exporter-prometheus", - "metrics-process", - "metrics-util", - "once_cell", - "procfs", "rand 0.8.5", "reth-chainspec", "reth-cli-util", @@ -9155,7 +8603,6 @@ dependencies = [ "reth-discv4", "reth-discv5", "reth-fs-util", - "reth-metrics", "reth-net-nat", "reth-network", "reth-network-p2p", @@ -9171,64 +8618,51 @@ dependencies = [ "reth-rpc-types-compat", "reth-stages-types", "reth-storage-errors", - "reth-tasks", "reth-tracing", "reth-transaction-pool", "secp256k1", + "serde", "serde_json", "shellexpand", - "tikv-jemalloc-ctl", - "tokio", - "tower", + "toml 0.8.15", "tracing", "vergen", ] [[package]] name = "reth-node-ethereum" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "eyre", - "futures", "reth-auto-seal-consensus", "reth-basic-payload-builder", "reth-beacon-consensus", + "reth-chainspec", "reth-consensus", - "reth-ethereum-engine", "reth-ethereum-engine-primitives", "reth-ethereum-payload-builder", "reth-evm-ethereum", - "reth-exex", "reth-network", "reth-node-api", "reth-node-builder", - "reth-node-core", - "reth-node-events", "reth-payload-builder", "reth-provider", "reth-rpc", - "reth-rpc-engine-api", - "reth-rpc-types", - "reth-tasks", - "reth-tokio-util", "reth-tracing", "reth-transaction-pool", - "tokio", - "tokio-stream", ] [[package]] name = "reth-node-events" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types-engine", "futures", "humantime", "pin-project", "reth-beacon-consensus", - "reth-db-api", "reth-network", "reth-network-api", "reth-primitives", @@ -9241,18 +8675,87 @@ dependencies = [ "tracing", ] +[[package]] +name = "reth-node-metrics" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "eyre", + "http 1.1.0", + "jsonrpsee 0.24.3", + "metrics", + "metrics-exporter-prometheus", + "metrics-process", + "metrics-util", + "procfs", + "reth-db-api", + "reth-metrics", + "reth-provider", + "reth-tasks", + "tikv-jemalloc-ctl", + "tokio", + "tower", + "tracing", + "vergen", +] + +[[package]] +name = "reth-optimism-consensus" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "reth-chainspec", + "reth-consensus", + "reth-consensus-common", + "reth-primitives", + "tracing", +] + [[package]] name = "reth-optimism-primitives" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" + +[[package]] +name = "reth-optimism-rpc" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "alloy-primitives 0.8.0", + "jsonrpsee-types 0.24.3", + "op-alloy-network", + "parking_lot 0.12.3", + "reqwest 0.12.5", + "reth-chainspec", + "reth-evm", + "reth-evm-optimism", + "reth-network-api", + "reth-node-api", + "reth-node-builder", + "reth-primitives", + "reth-provider", + "reth-rpc", + "reth-rpc-eth-api", + "reth-rpc-eth-types", + "reth-rpc-server-types", + "reth-rpc-types", + "reth-tasks", + "reth-transaction-pool", + "revm", + "serde_json", + "thiserror", + "tokio", + "tracing", +] [[package]] name = "reth-payload-builder" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "futures-util", "metrics", + "pin-project", "reth-errors", "reth-ethereum-engine-primitives", "reth-metrics", @@ -9269,9 +8772,10 @@ dependencies = [ [[package]] name = "reth-payload-primitives" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ + "reth-chain-state", "reth-chainspec", "reth-errors", "reth-primitives", @@ -9284,8 +8788,8 @@ dependencies = [ [[package]] name = "reth-payload-validator" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "reth-chainspec", "reth-primitives", @@ -9295,20 +8799,24 @@ dependencies = [ [[package]] name = "reth-primitives" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-rpc-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types", + "alloy-serde", "arbitrary", "bytes", "c-kzg", - "derive_more", + "derive_more 1.0.0", + "k256 0.13.3", "modular-bitfield", "once_cell", + "op-alloy-rpc-types", "proptest", "rayon", "reth-chainspec", @@ -9321,25 +8829,25 @@ dependencies = [ "secp256k1", "serde", "tempfile", - "thiserror-no-std", + "thiserror", "zstd 0.13.2", ] [[package]] name = "reth-primitives-traits" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-rpc-types-eth 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types-eth", "arbitrary", "byteorder", "bytes", - "derive_more", + "derive_more 1.0.0", "modular-bitfield", "proptest", "proptest-arbitrary-interop", @@ -9351,20 +8859,19 @@ dependencies = [ [[package]] name = "reth-provider" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-rlp", - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types-engine", "auto_impl", - "dashmap", - "derive_more", + "dashmap 6.0.1", "itertools 0.13.0", "metrics", + "once_cell", "parking_lot 0.12.3", - "pin-project", "rayon", "reth-blockchain-tree-api", + "reth-chain-state", "reth-chainspec", "reth-codecs", "reth-db", @@ -9382,19 +8889,19 @@ dependencies = [ "reth-storage-api", "reth-storage-errors", "reth-trie", + "reth-trie-db", "revm", "strum", "tokio", - "tokio-stream", "tracing", ] [[package]] name = "reth-prune" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "itertools 0.13.0", "metrics", "rayon", @@ -9417,12 +8924,12 @@ dependencies = [ [[package]] name = "reth-prune-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "bytes", - "derive_more", + "derive_more 1.0.0", "modular-bitfield", "reth-codecs", "serde", @@ -9431,10 +8938,9 @@ dependencies = [ [[package]] name = "reth-revm" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "reth-chainspec", "reth-consensus-common", "reth-execution-errors", @@ -9443,25 +8949,25 @@ dependencies = [ "reth-storage-api", "reth-storage-errors", "revm", - "tracing", ] [[package]] name = "reth-rpc" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-dyn-abi", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-genesis", + "alloy-network", + "alloy-primitives 0.8.0", "alloy-rlp", "async-trait", - "derive_more", + "derive_more 1.0.0", "futures", "http 1.1.0", "http-body 1.0.1", "hyper 1.4.1", - "jsonrpsee 0.23.2", + "jsonrpsee 0.24.3", "jsonwebtoken", "parking_lot 0.12.3", "pin-project", @@ -9472,6 +8978,7 @@ dependencies = [ "reth-evm", "reth-network-api", "reth-network-peers", + "reth-network-types", "reth-node-api", "reth-primitives", "reth-provider", @@ -9485,6 +8992,7 @@ dependencies = [ "reth-rpc-types-compat", "reth-tasks", "reth-transaction-pool", + "reth-trie", "revm", "revm-inspectors", "revm-primitives", @@ -9501,10 +9009,11 @@ dependencies = [ [[package]] name = "reth-rpc-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "jsonrpsee 0.23.2", + "alloy-json-rpc", + "jsonrpsee 0.24.3", "reth-engine-primitives", "reth-network-peers", "reth-primitives", @@ -9514,13 +9023,14 @@ dependencies = [ [[package]] name = "reth-rpc-builder" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "http 1.1.0", - "jsonrpsee 0.23.2", + "jsonrpsee 0.24.3", "metrics", "pin-project", + "reth-chainspec", "reth-engine-primitives", "reth-evm", "reth-ipc", @@ -9534,6 +9044,7 @@ dependencies = [ "reth-rpc-eth-types", "reth-rpc-layer", "reth-rpc-server-types", + "reth-rpc-types", "reth-tasks", "reth-transaction-pool", "serde", @@ -9545,12 +9056,12 @@ dependencies = [ [[package]] name = "reth-rpc-engine-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "async-trait", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", "metrics", "reth-beacon-consensus", "reth-chainspec", @@ -9573,20 +9084,24 @@ dependencies = [ [[package]] name = "reth-rpc-eth-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-dyn-abi", + "alloy-json-rpc", + "alloy-network", "async-trait", "auto_impl", "dyn-clone", "futures", - "jsonrpsee 0.23.2", + "jsonrpsee 0.24.3", + "jsonrpsee-types 0.24.3", "parking_lot 0.12.3", "reth-chainspec", "reth-errors", "reth-evm", "reth-execution-types", + "reth-network-api", "reth-primitives", "reth-provider", "reth-revm", @@ -9596,6 +9111,7 @@ dependencies = [ "reth-rpc-types-compat", "reth-tasks", "reth-transaction-pool", + "reth-trie", "revm", "revm-inspectors", "revm-primitives", @@ -9605,27 +9121,28 @@ dependencies = [ [[package]] name = "reth-rpc-eth-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-sol-types", - "derive_more", + "derive_more 1.0.0", "futures", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", "metrics", "rand 0.8.5", + "reth-chain-state", "reth-chainspec", "reth-errors", "reth-evm", "reth-execution-types", "reth-metrics", "reth-primitives", - "reth-provider", "reth-revm", "reth-rpc-server-types", "reth-rpc-types", "reth-rpc-types-compat", + "reth-storage-api", "reth-tasks", "reth-transaction-pool", "reth-trie", @@ -9642,12 +9159,12 @@ dependencies = [ [[package]] name = "reth-rpc-layer" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types-engine", "http 1.1.0", - "jsonrpsee-http-client 0.23.2", + "jsonrpsee-http-client 0.24.3", "pin-project", "tower", "tracing", @@ -9655,12 +9172,12 @@ dependencies = [ [[package]] name = "reth-rpc-server-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", - "jsonrpsee-core 0.23.2", - "jsonrpsee-types 0.23.2", + "alloy-primitives 0.8.0", + "jsonrpsee-core 0.24.3", + "jsonrpsee-types 0.24.3", "reth-errors", "reth-network-api", "reth-primitives", @@ -9671,29 +9188,31 @@ dependencies = [ [[package]] name = "reth-rpc-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", - "alloy-rpc-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-primitives 0.8.0", + "alloy-rpc-types", "alloy-rpc-types-admin", "alloy-rpc-types-anvil", - "alloy-rpc-types-beacon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-rpc-types-engine 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types-beacon", + "alloy-rpc-types-engine", "alloy-rpc-types-mev", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpsee-types 0.23.2", + "alloy-serde", + "jsonrpsee-types 0.24.3", + "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", ] [[package]] name = "reth-rpc-types-compat" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", - "alloy-rpc-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-rpc-types", "reth-primitives", "reth-rpc-types", "reth-trie-common", @@ -9701,8 +9220,8 @@ dependencies = [ [[package]] name = "reth-stages" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "futures-util", "itertools 0.13.0", @@ -9727,6 +9246,7 @@ dependencies = [ "reth-stages-api", "reth-storage-errors", "reth-trie", + "reth-trie-db", "thiserror", "tokio", "tracing", @@ -9734,10 +9254,10 @@ dependencies = [ [[package]] name = "reth-stages-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "aquamarine", "auto_impl", "futures-util", @@ -9761,10 +9281,10 @@ dependencies = [ [[package]] name = "reth-stages-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "bytes", "modular-bitfield", "reth-codecs", @@ -9774,10 +9294,10 @@ dependencies = [ [[package]] name = "reth-static-file" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "parking_lot 0.12.3", "rayon", "reth-db", @@ -9794,47 +9314,47 @@ dependencies = [ [[package]] name = "reth-static-file-types" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.8.0", "clap", - "derive_more", + "derive_more 1.0.0", "serde", "strum", ] [[package]] name = "reth-storage-api" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "auto_impl", "reth-chainspec", - "reth-db-api", + "reth-db-models", "reth-execution-types", "reth-primitives", "reth-prune-types", "reth-stages-types", "reth-storage-errors", "reth-trie", - "revm", ] [[package]] name = "reth-storage-errors" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ + "alloy-rlp", + "derive_more 1.0.0", "reth-fs-util", "reth-primitives", - "thiserror-no-std", ] [[package]] name = "reth-tasks" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "auto_impl", "dyn-clone", @@ -9851,8 +9371,8 @@ dependencies = [ [[package]] name = "reth-tokio-util" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "tokio", "tokio-stream", @@ -9861,8 +9381,8 @@ dependencies = [ [[package]] name = "reth-tracing" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "clap", "eyre", @@ -9876,8 +9396,8 @@ dependencies = [ [[package]] name = "reth-transaction-pool" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "aquamarine", @@ -9886,13 +9406,14 @@ dependencies = [ "futures-util", "metrics", "parking_lot 0.12.3", + "reth-chain-state", "reth-chainspec", "reth-eth-wire-types", "reth-execution-types", "reth-fs-util", "reth-metrics", "reth-primitives", - "reth-provider", + "reth-storage-api", "reth-tasks", "revm", "rustc-hash 2.0.0", @@ -9907,53 +9428,80 @@ dependencies = [ [[package]] name = "reth-trie" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", "auto_impl", - "derive_more", + "derive_more 1.0.0", "itertools 0.13.0", "metrics", "rayon", - "reth-db", - "reth-db-api", "reth-execution-errors", "reth-metrics", "reth-primitives", "reth-stages-types", + "reth-storage-errors", "reth-trie-common", "revm", "tracing", + "triehash", ] [[package]] name = "reth-trie-common" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ - "alloy-consensus 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-genesis 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-consensus", + "alloy-genesis", + "alloy-primitives 0.8.0", "alloy-rlp", "alloy-trie", + "arbitrary", "bytes", - "derive_more", + "derive_more 1.0.0", + "hash-db", "itertools 0.13.0", "nybbles", + "plain_hasher", "reth-codecs", "reth-primitives-traits", "revm-primitives", "serde", ] +[[package]] +name = "reth-trie-db" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" +dependencies = [ + "alloy-rlp", + "auto_impl", + "derive_more 1.0.0", + "itertools 0.13.0", + "metrics", + "rayon", + "reth-db", + "reth-db-api", + "reth-execution-errors", + "reth-metrics", + "reth-primitives", + "reth-stages-types", + "reth-storage-errors", + "reth-trie", + "reth-trie-common", + "revm", + "tracing", +] + [[package]] name = "reth-trie-parallel" -version = "1.0.3" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.3#390f30aadebcdd509e72cc04327c3b854de076a6" +version = "1.0.6" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.0.6#c228fe15808c3acbf18dc3af1a03ef5cbdcda07a" dependencies = [ "alloy-rlp", - "derive_more", + "derive_more 1.0.0", "itertools 0.13.0", "metrics", "rayon", @@ -9965,6 +9513,7 @@ dependencies = [ "reth-provider", "reth-tasks", "reth-trie", + "reth-trie-db", "thiserror", "tokio", "tracing", @@ -9972,9 +9521,9 @@ dependencies = [ [[package]] name = "revm" -version = "12.1.0" +version = "14.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cfb48bce8ca2113e157bdbddbd5eeb09daac1c903d79ec17085897c38c7c91" +checksum = "1f719e28cc6fdd086f8bc481429e587740d20ad89729cec3f5f5dd7b655474df" dependencies = [ "auto_impl", "cfg-if", @@ -9987,16 +9536,14 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af2dc001e37ac3b061dc9087876aea91e28756c188a97cd99416d23a5562ca73" +checksum = "48184032103bb23788e42e42c7c85207f5b0b8a248b09ea8f5233077f35ab56e" dependencies = [ - "alloy-primitives", - "alloy-rpc-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-primitives 0.8.0", + "alloy-rpc-types", "alloy-sol-types", "anstyle", - "boa_engine", - "boa_gc", "colorchoice", "revm", "serde_json", @@ -10005,9 +9552,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "8.1.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b0daddea06fc6da5346acc39b32a357bbe3579e9e3d94117d9ae125cd596fc" +checksum = "959ecbc36802de6126852479844737f20194cf8e6718e0c30697d306a2cca916" dependencies = [ "revm-primitives", "serde", @@ -10015,9 +9562,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "9.2.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef55228211251d7b6c7707c3ee13bb70dea4d2fd81ec4034521e4fe31010b2ea" +checksum = "6e25f604cb9db593ca3013be8c00f310d6790ccb1b7d8fbbdd4660ec8888043a" dependencies = [ "aurora-engine-modexp", "blst", @@ -10034,24 +9581,21 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "7.1.0" +version = "9.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc4311037ee093ec50ec734e1424fcb3e12d535c6cef683b75d1c064639630c" +checksum = "0ccb981ede47ccf87c68cebf1ba30cdbb7ec935233ea305f3dfff4c1e10ae541" dependencies = [ - "alloy-eips 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "alloy-primitives", + "alloy-eips", + "alloy-primitives 0.8.0", "auto_impl", "bitflags 2.6.0", "bitvec", "c-kzg", "cfg-if", - "derive_more", "dyn-clone", "enumn", "hashbrown 0.14.5", "hex", - "kzg-rs", - "once_cell", "serde", ] @@ -10193,7 +9737,6 @@ dependencies = [ "ark-ff 0.3.0", "ark-ff 0.4.2", "bytes", - "ethereum_ssz", "fastrlp", "num-bigint", "num-traits", @@ -10412,29 +9955,12 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "rw-stream-sink" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c9026ff5d2f23da5e45bbc283f156383001bfb09c4e44256d02c1a685fe9a1" -dependencies = [ - "futures", - "pin-project", - "static_assertions", -] - [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "ryu-js" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" - [[package]] name = "same-file" version = "1.0.6" @@ -10451,7 +9977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", - "derive_more", + "derive_more 0.99.18", "parity-scale-codec", "scale-info-derive", ] @@ -10607,7 +10133,7 @@ checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" dependencies = [ "bitflags 2.6.0", "cssparser", - "derive_more", + "derive_more 0.99.18", "fxhash", "log", "new_debug_unreachable", @@ -10760,7 +10286,7 @@ version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.20.10", + "darling", "proc-macro2", "quote", "syn 2.0.72", @@ -10778,19 +10304,6 @@ dependencies = [ "yaml-rust", ] -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.2.6", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - [[package]] name = "servo_arc" version = "0.3.0" @@ -11013,6 +10526,7 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ + "arbitrary", "serde", ] @@ -11123,12 +10637,6 @@ dependencies = [ "der 0.7.9", ] -[[package]] -name = "sptr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" - [[package]] name = "sqlformat" version = "0.2.4" @@ -11364,7 +10872,7 @@ name = "ssz_rs" version = "0.9.0" source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.7", "bitvec", "serde", "sha2 0.9.9", @@ -11376,7 +10884,7 @@ name = "ssz_rs" version = "0.9.0" source = "git+https://github.com/ralexstokes/ssz-rs.git#84ef2b71aa004f6767420badb42c902ad56b8b72" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.7", "bitvec", "serde", "sha2 0.9.9", @@ -11483,12 +10991,6 @@ dependencies = [ "unicode-properties", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -11583,9 +11085,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" +checksum = "284c41c2919303438fcf8dede4036fd1e82d4fc0fbb2b279bd2a1442c909ca92" dependencies = [ "paste", "proc-macro2", @@ -11617,17 +11119,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - [[package]] name = "sysinfo" version = "0.29.11" @@ -11729,12 +11220,6 @@ dependencies = [ "which", ] -[[package]] -name = "thin-vec" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" - [[package]] name = "thiserror" version = "1.0.63" @@ -11833,7 +11318,6 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", - "js-sys", "libc", "num-conv", "num_threads", @@ -11868,16 +11352,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -12256,6 +11730,16 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" +dependencies = [ + "hash-db", + "rlp", +] + [[package]] name = "trust-dns-proto" version = "0.23.2" @@ -12375,7 +11859,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ - "arbitrary", "byteorder", "crunchy", "hex", @@ -12461,32 +11944,20 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "universal-hash" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "generic-array", + "crypto-common", "subtle", ] -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "unsigned-varint" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" -[[package]] -name = "unsigned-varint" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" - [[package]] name = "untrusted" version = "0.9.0" @@ -12533,18 +12004,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -12594,12 +12053,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "wait-timeout" version = "0.2.0" @@ -12770,16 +12223,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-roots" version = "0.25.4" @@ -13103,18 +12546,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -13167,30 +12598,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", - "synstructure 0.13.1", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -13211,27 +12618,6 @@ dependencies = [ "syn 2.0.72", ] -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", - "synstructure 0.13.1", -] - [[package]] name = "zeroize" version = "1.8.1" @@ -13252,35 +12638,13 @@ dependencies = [ "syn 2.0.72", ] -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - [[package]] name = "zip" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "aes 0.8.4", + "aes", "byteorder", "bzip2", "constant_time_eq", diff --git a/Cargo.toml b/Cargo.toml index d5d773ec..cf448b64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,56 +22,56 @@ version = "0.1.0" edition = "2021" [workspace.dependencies] -reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-libmdbx = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-trie-parallel = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-basic-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3", features = ["test-utils"] } -reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } -reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.3" } +reth = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-libmdbx = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-trie-parallel = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-basic-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6", features = ["test-utils"] } +reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } +reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.0.6" } -# version is copied from reth "v1.0.3" dependencies -revm = { version = "12.1.0", features = [ +# version is copied from reth "v1.0.6" dependencies +revm = { version = "14.0.0", features = [ "std", "secp256k1", "optional_balance_check", ], default-features = false } -revm-primitives = { version = "7.1.0", features = [ +revm-inspectors = "0.6" +revm-primitives = { version = "9.0.0", features = [ "std", ], default-features = false } -revm-inspectors = "0.5" -ethereum_ssz_derive = "0.5" -ethereum_ssz = "0.5" +ethereum_ssz_derive = "0.7" +ethereum_ssz = "0.7" -alloy-primitives = "0.7.2" +alloy-primitives = { version = "0.8.0", default-features = false } alloy-rlp = "0.3.4" alloy-chains = "0.1.23" -alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032", features = ["ipc", "pubsub"] } -alloy-pubsub = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032", features = ["kzg"] } -alloy-serde = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-rpc-types-beacon = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032", features = [ +alloy-provider = { version = "0.3.0", features = ["ipc", "pubsub"] } +alloy-pubsub = { version = "0.3.0" } +alloy-eips = { version = "0.3.0" } +alloy-rpc-types = { version = "0.3.0" } +alloy-json-rpc = { version = "0.3.0" } +alloy-transport-http = { version = "0.3.0" } +alloy-network = { version = "0.3.0" } +alloy-transport = { version = "0.3.0" } +alloy-node-bindings = { version = "0.3.0" } +alloy-consensus = { version = "0.3.0", features = ["kzg"] } +alloy-serde = { version = "0.3.0" } +alloy-rpc-types-beacon = { version = "0.3.0", features = [ "ssz", ] } -alloy-rpc-types-engine = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032", features = [ +alloy-rpc-types-engine = { version = "0.3.0", features = [ "ssz", ] } -alloy-rpc-types-eth = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } -alloy-signer-local = { git = "https://github.com/alloy-rs/alloy", rev = "f2d80032" } +alloy-rpc-types-eth = { version = "0.3.0" } +alloy-signer-local = { version = "0.3.0" } \ No newline at end of file diff --git a/crates/rbuilder/benches/benchmarks/txpool_fetcher.rs b/crates/rbuilder/benches/benchmarks/txpool_fetcher.rs index d7637ce9..f68d0d11 100644 --- a/crates/rbuilder/benches/benchmarks/txpool_fetcher.rs +++ b/crates/rbuilder/benches/benchmarks/txpool_fetcher.rs @@ -45,8 +45,9 @@ async fn txpool_receive_util(count: u32) { .with_max_priority_fee_per_gas(eip1559_est.max_priority_fee_per_gas); tokio::spawn(async move { - for _ in 0..count { - let _ = provider.send_transaction(tx.clone()).await.unwrap(); + for i in 0..count { + let tx = tx.clone().with_nonce(i.into()); + let _ = provider.send_transaction(tx).await.unwrap(); } }); @@ -63,8 +64,8 @@ fn bench_txpool_receive(c: &mut Criterion) { group.bench_function("txn_fetcher_normal_10", |b| { b.to_async(&rt).iter(|| txpool_receive_util(10)); }); - group.bench_function("txn_fetcher_normal_100", |b| { - b.to_async(&rt).iter(|| txpool_receive_util(100)); + group.bench_function("txn_fetcher_normal_50", |b| { + b.to_async(&rt).iter(|| txpool_receive_util(50)); }); } diff --git a/crates/rbuilder/src/backtest/backtest_build_block.rs b/crates/rbuilder/src/backtest/backtest_build_block.rs index 36a7e94f..8062f565 100644 --- a/crates/rbuilder/src/backtest/backtest_build_block.rs +++ b/crates/rbuilder/src/backtest/backtest_build_block.rs @@ -209,8 +209,7 @@ async fn read_block_data( println!( "Block: {} {:?}", - block_data.block_number, - block_data.onchain_block.header.hash.unwrap_or_default() + block_data.block_number, block_data.onchain_block.header.hash ); println!( "bid value: {}", diff --git a/crates/rbuilder/src/backtest/fetch/mod.rs b/crates/rbuilder/src/backtest/fetch/mod.rs index 014ea9be..bbc01a6d 100644 --- a/crates/rbuilder/src/backtest/fetch/mod.rs +++ b/crates/rbuilder/src/backtest/fetch/mod.rs @@ -222,7 +222,11 @@ impl HistoricalDataFetcher { let mut orders: Vec = vec![]; let mut built_block_data = None; - let block_ref = BlockRef::new(block_number, block_timestamp, onchain_block.header.hash); + let block_ref = BlockRef::new( + block_number, + block_timestamp, + Some(onchain_block.header.hash), + ); for datasource in &self.data_sources { let mut data = datasource.get_data(block_ref).await?; diff --git a/crates/rbuilder/src/backtest/redistribute/cli/mod.rs b/crates/rbuilder/src/backtest/redistribute/cli/mod.rs index 15ccd3c6..9a904bbb 100644 --- a/crates/rbuilder/src/backtest/redistribute/cli/mod.rs +++ b/crates/rbuilder/src/backtest/redistribute/cli/mod.rs @@ -116,7 +116,7 @@ fn process_redisribution( distribute_to_mempool_txs: bool, ) -> eyre::Result<()> { let block_number = block_data.block_number; - let block_hash = block_data.onchain_block.header.hash.unwrap_or_default(); + let block_hash = block_data.onchain_block.header.hash; info!(block_number, "Calculating redistribution for a block"); let redistribution_values = match calc_redistributions( provider_factory.clone(), diff --git a/crates/rbuilder/src/backtest/redistribute/mod.rs b/crates/rbuilder/src/backtest/redistribute/mod.rs index 65953c55..aed7f5db 100644 --- a/crates/rbuilder/src/backtest/redistribute/mod.rs +++ b/crates/rbuilder/src/backtest/redistribute/mod.rs @@ -222,7 +222,7 @@ fn get_available_orders( } if distribute_to_mempool_txs { for tx in block_data.onchain_block.transactions.hashes() { - let id = OrderId::Tx(*tx); + let id = OrderId::Tx(tx); if let Some(order) = orders_by_id.get(&id) { included_orders_available.insert(order.order.id(), order.clone()); } @@ -720,7 +720,7 @@ fn collect_redistribution_result( ) -> RedistributionBlockOutput { let mut result = RedistributionBlockOutput { block_number: block_data.block_number, - block_hash: block_data.onchain_block.header.hash.unwrap_or_default(), + block_hash: block_data.onchain_block.header.hash, block_profit: onchain_block_profit, identities: Vec::new(), landed_orders: Vec::new(), diff --git a/crates/rbuilder/src/backtest/store.rs b/crates/rbuilder/src/backtest/store.rs index 5296e39d..56f5b02b 100644 --- a/crates/rbuilder/src/backtest/store.rs +++ b/crates/rbuilder/src/backtest/store.rs @@ -623,7 +623,6 @@ mod test { }; use alloy_primitives::{hex, Address, Bloom, Bytes, B256}; use alloy_rpc_types::{Block, BlockTransactions, Header, Signature, Transaction}; - use alloy_serde::OtherFields; use reth_primitives::{U256, U64}; use time::OffsetDateTime; #[tokio::test] @@ -724,7 +723,7 @@ mod test { fn create_empty_block_header() -> Header { Header { - hash: None, + hash: B256::default(), parent_hash: B256::default(), uncles_hash: B256::default(), miner: Address::default(), @@ -733,7 +732,7 @@ mod test { receipts_root: B256::default(), logs_bloom: Bloom::default(), difficulty: U256::default(), - number: None, + number: 0, gas_limit: 0, gas_used: 0, timestamp: 0, @@ -759,7 +758,6 @@ mod test { transactions: BlockTransactions::Full(vec![create_test_tx()]), size: None, withdrawals: None, - other: OtherFields::default(), } } @@ -789,7 +787,6 @@ mod test { max_fee_per_gas: Some(21), max_priority_fee_per_gas: Some(22), max_fee_per_blob_gas: None, - other: Default::default(), authorization_list: None, } } diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index ff8adf32..c785cef5 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -156,7 +156,7 @@ impl BlockBuildingContext { suggested_fee_recipient: Address, builder_signer: Option, ) -> BlockBuildingContext { - let block_number = onchain_block.header.number.unwrap_or(1); + let block_number = onchain_block.header.number; let blob_excess_gas_and_price = if chain_spec.is_cancun_active_at_timestamp(onchain_block.header.timestamp) { @@ -230,7 +230,7 @@ impl BlockBuildingContext { /// Useless BlockBuildingContext for testing in contexts where we can't avoid having a BlockBuildingContext. pub fn dummy_for_testing() -> Self { - let mut onchain_block = alloy_rpc_types::Block::default(); + let mut onchain_block: alloy_rpc_types::Block = Default::default(); onchain_block.header.base_fee_per_gas = Some(0); BlockBuildingContext::from_onchain_block( onchain_block, @@ -708,8 +708,6 @@ impl PartialBlock { &ctx.chain_spec, &ctx.initialized_cfg, &ctx.block_env, - ctx.block_env.number.to(), - ctx.attributes.timestamp(), ctx.attributes.parent_beacon_block_root(), )?; db.as_mut().merge_transitions(BundleRetention::Reverts); diff --git a/crates/rbuilder/src/live_builder/order_input/clean_orderpool.rs b/crates/rbuilder/src/live_builder/order_input/clean_orderpool.rs index 70273fd4..0d687dfa 100644 --- a/crates/rbuilder/src/live_builder/order_input/clean_orderpool.rs +++ b/crates/rbuilder/src/live_builder/order_input/clean_orderpool.rs @@ -45,7 +45,7 @@ pub async fn spawn_clean_orderpool_job( while let Some(block) = new_block_stream.next().await { let provider_factory = provider_factory.provider_factory_unchecked(); - let block_number = block.header.number.unwrap_or_default(); + let block_number = block.header.number; set_current_block(block_number); let state = match provider_factory.latest() { Ok(state) => state, From a00be29a28181baff42058fd1b1146a825566d2c Mon Sep 17 00:00:00 2001 From: liamaharon Date: Sat, 14 Sep 2024 02:20:13 +1000 Subject: [PATCH 10/30] redact_sensitive feature flag (#176) demo for @ZanCorDX Idea is to redact the error `Display` and `Debug` implementation where the error is defined, rather than creating new layers of wrapper we need to maintain and remember to use --------- Co-authored-by: Daniel Xifra --- .github/workflows/checks.yaml | 27 ++-- .github/workflows/release.yaml | 19 ++- Dockerfile | 4 +- Makefile | 14 +- crates/rbuilder/Cargo.toml | 3 + .../live_builder/block_output/relay_submit.rs | 131 +++++++++--------- crates/rbuilder/src/mev_boost/error.rs | 116 ++++++++++++++++ crates/rbuilder/src/mev_boost/mod.rs | 67 ++++----- crates/rbuilder/src/utils/mod.rs | 1 + crates/rbuilder/src/utils/tracing.rs | 15 ++ crates/rbuilder/src/validation_api_client.rs | 39 ++++-- docs/LOGS_PRIVACY.md | 90 ++++++++++++ 12 files changed, 386 insertions(+), 140 deletions(-) create mode 100644 crates/rbuilder/src/mev_boost/error.rs create mode 100644 crates/rbuilder/src/utils/tracing.rs create mode 100644 docs/LOGS_PRIVACY.md diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index d4bd932e..3960f646 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -14,12 +14,16 @@ jobs: lint_and_test: name: Lint and test runs-on: warp-ubuntu-latest-x64-16x + env: + # Set features for the Makefile + FEATURES: ${{ matrix.features }} strategy: matrix: toolchain: - stable - #- beta - #- nightly + features: + - "" + - "redact_sensitive" steps: - name: Checkout sources uses: actions/checkout@v4 @@ -53,9 +57,11 @@ jobs: - name: Install native dependencies run: sudo apt-get install -y libsqlite3-dev - # lint and test - - run: make lint - - run: make test + - name: Lint + run: make lint + + - name: Test + run: make test integration: name: Integration tests @@ -65,8 +71,9 @@ jobs: matrix: toolchain: - stable - #- beta - #- nightly + features: + - "" + - "redact_sensitive" steps: - name: Checkout sources uses: actions/checkout@v4 @@ -92,13 +99,13 @@ jobs: echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV - name: Build the rbuilder - run: cargo build + run: cargo build --features="${{ matrix.features }}" - name: Run the playground run: builder-playground & - - name: Run integration tests - run: cargo test --package rbuilder --lib -- integration + - name: Run integration tests with flags + run: cargo test --features="${{ matrix.features }}" --package rbuilder --lib -- integration env: PLAYGROUND: TRUE diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6578074d..49422ecd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -3,21 +3,21 @@ name: Release on: push: tags: - - 'v*' + - "v*" workflow_dispatch: inputs: build-docker: - description: 'Build Docker' + description: "Build Docker" required: false type: boolean default: false build-binary: - description: 'Build Binary' + description: "Build Binary" required: false type: boolean default: true draft-release: - description: 'Draft Release' + description: "Draft Release" required: false type: boolean default: false @@ -77,6 +77,9 @@ jobs: runner: warp-ubuntu-latest-arm64-16x - target: aarch64-apple-darwin runner: warp-macos-14-arm64-6x + features: + - "" + - "redact_sensitive" steps: - name: Checkout sources @@ -107,12 +110,16 @@ jobs: - name: Prepare output filename run: | - OUTPUT_FILENAME="rbuilder-${VERSION}-${{ matrix.configs.target }}.tar.gz" + if [ -z "${{ matrix.features }}" ]; then + OUTPUT_FILENAME="rbuilder-${VERSION}-${{ matrix.configs.target }}.tar.gz" + else + OUTPUT_FILENAME="rbuilder-${VERSION}-${{ matrix.configs.target }}-${{ matrix.features }}.tar.gz" + fi echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV echo "Filename: ${OUTPUT_FILENAME}" - name: Build rbuilder binary - run: cargo build --release + run: cargo build --release --features=${{ matrix.features }} - name: Prepare artifacts run: | diff --git a/Dockerfile b/Dockerfile index 25e85568..4ab98ff1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,8 @@ # FROM rust:1.79 as base +ARG FEATURES + RUN cargo install sccache --version ^0.8 RUN cargo install cargo-chef --version ^0.1 @@ -53,7 +55,7 @@ COPY ./crates/ ./crates/ RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ - cargo build --release + cargo build --release --features="$FEATURES" # # Runtime container diff --git a/Makefile b/Makefile index 651bd6d4..7078179b 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,8 @@ GIT_VER ?= $(shell git describe --tags --always --dirty="-dev") GIT_TAG ?= $(shell git describe --tags --abbrev=0) +FEATURES ?= + ##@ Help .PHONY: help @@ -23,22 +25,22 @@ clean: ## Clean up .PHONY: build build: ## Build (debug version) - cargo build + cargo build --features "$(FEATURES)" .PHONY: docker-image docker-image: ## Build a rbuilder Docker image - docker build --platform linux/amd64 . -t rbuilder + docker build --platform linux/amd64 --build-arg FEATURES="$(FEATURES)" . -t rbuilder ##@ Dev .PHONY: lint lint: ## Run the linters cargo fmt -- --check - cargo clippy -- -D warnings + cargo clippy --features "$(FEATURES)" -- -D warnings .PHONY: test test: ## Run the tests - cargo test --verbose + cargo test --verbose --features "$(FEATURES)" .PHONY: lt lt: lint test ## Run "lint" and "test" @@ -47,11 +49,11 @@ lt: lint test ## Run "lint" and "test" fmt: ## Format the code cargo fmt cargo fix --allow-staged - cargo clippy --fix --allow-staged + cargo clippy --features "$(FEATURES)" --fix --allow-staged .PHONY: bench bench: ## Run benchmarks - cargo bench --bench bench_main + cargo bench --features "$(FEATURES)" --bench bench_main # cargo bench --bench bench_main -- --verbose .PHONY: bench-report-open diff --git a/crates/rbuilder/Cargo.toml b/crates/rbuilder/Cargo.toml index c98276df..bf0d29cf 100644 --- a/crates/rbuilder/Cargo.toml +++ b/crates/rbuilder/Cargo.toml @@ -134,3 +134,6 @@ criterion = { version = "0.5.1", features = ["html_reports", "async_tokio"] } [[bench]] name = "bench_main" harness = false + +[features] +redact_sensitive = [] diff --git a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs index 1b9d3c86..13100fb9 100644 --- a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs +++ b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs @@ -11,8 +11,8 @@ use crate::{ inc_relay_accepted_submissions, inc_subsidized_blocks, inc_too_many_req_relay_errors, measure_block_e2e_latency, }, - utils::error_storage::store_error_event, - validation_api_client::{ValdationError, ValidationAPIClient}, + utils::{error_storage::store_error_event, tracing::dynamic_event}, + validation_api_client::{ValidationAPIClient, ValidationError}, }; use ahash::HashMap; use alloy_primitives::{utils::format_ether, U256}; @@ -25,7 +25,7 @@ use std::{ }; use tokio::time::{sleep, Instant}; use tokio_util::sync::CancellationToken; -use tracing::{debug, error, info_span, trace, warn, Instrument}; +use tracing::{debug, error, event, info_span, trace, warn, Instrument, Level}; use super::bid_observer::BidObserver; @@ -266,31 +266,16 @@ async fn run_submit_to_relays_job( }; if config.dry_run { - match validate_block( + validate_block( &slot_data, &normal_signed_submission, block.sealed_block.clone(), &config, cancel.clone(), + "Dry run", ) - .await - { - Ok(()) => { - trace!(parent: &submission_span, "Dry run validation passed"); - } - Err(ValdationError::UnableToValidate(err)) => { - warn!(parent: &submission_span, err, "Failed to validate payload"); - } - Err(ValdationError::ValidationFailed(err)) => { - error!(parent: &submission_span, err = ?err, "Dry run validation failed"); - inc_failed_block_simulations(); - store_error_event( - VALIDATION_ERROR_CATEGORY, - &err.to_string(), - &normal_signed_submission, - ); - } - } + .instrument(submission_span) + .await; continue 'submit; } @@ -311,38 +296,16 @@ async fn run_submit_to_relays_job( if submission_optimistic { let can_submit = if config.optimistic_prevalidate_optimistic_blocks { - let start = Instant::now(); - match validate_block( + validate_block( &slot_data, &optimistic_signed_submission, block.sealed_block.clone(), &config, cancel.clone(), + "Optimistic check", ) + .instrument(submission_span.clone()) .await - { - Ok(()) => { - trace!(parent: &submission_span, - time_ms = start.elapsed().as_millis(), - "Optimistic validation passed" - ); - true - } - Err(ValdationError::UnableToValidate(err)) => { - warn!(parent: &submission_span, err = ?err, "Failed to validate optimistic payload"); - false - } - Err(ValdationError::ValidationFailed(err)) => { - error!(parent: &submission_span, err = ?err, "Optimistic Payload Validation failed"); - inc_failed_block_simulations(); - store_error_event( - VALIDATION_ERROR_CATEGORY, - &err.to_string(), - &optimistic_signed_submission, - ); - false - } - } } else { true }; @@ -415,16 +378,23 @@ pub async fn run_submit_to_relays_job_and_metrics( } } +fn log_validation_error(err: ValidationError, level: Level, validation_use: &str) { + dynamic_event!(level,err = ?err, validation_use,"Validation failed"); +} + +/// Validates the blocks handling any logging. +/// Answers if the block was validated ok. async fn validate_block( slot_data: &MevBoostSlotData, signed_submit_request: &SubmitBlockRequest, block: SealedBlock, config: &SubmissionConfig, cancellation_token: CancellationToken, -) -> Result<(), ValdationError> { + validation_use: &str, +) -> bool { let withdrawals_root = block.withdrawals_root.unwrap_or_default(); - - config + let start = Instant::now(); + match config .validation_api .validate_block( signed_submit_request, @@ -433,8 +403,35 @@ async fn validate_block( block.parent_beacon_block_root, cancellation_token, ) - .await?; - Ok(()) + .await + { + Ok(()) => { + trace!( + time_ms = start.elapsed().as_millis(), + validation_use, + "Validation passed" + ); + true + } + Err(ValidationError::ValidationFailed(err)) => { + log_validation_error( + ValidationError::ValidationFailed(err.clone()), + Level::ERROR, + validation_use, + ); + inc_failed_block_simulations(); + store_error_event( + VALIDATION_ERROR_CATEGORY, + &err.to_string(), + signed_submit_request, + ); + false + } + Err(err) => { + log_validation_error(err, Level::WARN, validation_use); + false + } + } } async fn submit_bid_to_the_relay( @@ -470,12 +467,22 @@ async fn submit_bid_to_the_relay( cancel.cancel(); } Err(SubmitBlockErr::BidBelowFloor | SubmitBlockErr::PayloadAttributesNotKnown) => { - trace!(err = ?relay_result.unwrap_err(), "Block not accepted by the relay"); + trace!( + err = ?relay_result.unwrap_err(), + "Block not accepted by the relay" + ); } - Err(SubmitBlockErr::SimError(err)) => { + Err(SubmitBlockErr::SimError(_)) => { inc_failed_block_simulations(); - error!(err = ?err, "Error block simulation fail, cancelling"); - store_error_event(SIM_ERROR_CATEGORY, &err.to_string(), &signed_submit_request); + store_error_event( + SIM_ERROR_CATEGORY, + relay_result.as_ref().unwrap_err().to_string().as_str(), + &signed_submit_request, + ); + error!( + err = ?relay_result.unwrap_err(), + "Error block simulation fail, cancelling" + ); cancel.cancel(); } Err(SubmitBlockErr::RelayError(RelayError::TooManyRequests)) => { @@ -490,19 +497,19 @@ async fn submit_bid_to_the_relay( Err(SubmitBlockErr::BlockKnown) => { trace!("Block already known"); } - Err(SubmitBlockErr::RelayError(err)) => { - warn!(err = ?err, "Error submitting block to the relay"); + Err(SubmitBlockErr::RelayError(_)) => { + warn!(err = ?relay_result.unwrap_err(), "Error submitting block to the relay"); inc_other_relay_errors(&relay.id); } - Err(SubmitBlockErr::RPCConversionError(err)) => { + Err(SubmitBlockErr::RPCConversionError(_)) => { error!( - err = ?err, + err = ?relay_result.unwrap_err(), "RPC conversion error (illegal submission?) submitting block to the relay", ); } - Err(SubmitBlockErr::RPCSerializationError(err)) => { + Err(SubmitBlockErr::RPCSerializationError(_)) => { error!( - err = ?err, + err = ?relay_result.unwrap_err(), "SubmitBlock serialization error submitting block to the relay", ); } diff --git a/crates/rbuilder/src/mev_boost/error.rs b/crates/rbuilder/src/mev_boost/error.rs new file mode 100644 index 00000000..4517b17a --- /dev/null +++ b/crates/rbuilder/src/mev_boost/error.rs @@ -0,0 +1,116 @@ +use reqwest::{self, StatusCode}; +use serde::{Deserialize, Serialize}; +use std::fmt::{self, Debug, Display, Formatter}; +use thiserror::Error; + +#[derive(Error)] +pub enum RelayError { + #[error("Request error: {0}")] + RequestError(#[from] RedactableReqwestError), + #[error("Header error")] + InvalidHeader, + #[error("Relay error: {0}")] + RelayError(#[from] RedactableRelayErrorResponse), + + #[cfg_attr( + not(feature = "redact_sensitive"), + error("Unknown relay response, status: {0}, body: {1}") + )] + #[cfg_attr( + feature = "redact_sensitive", + error("Unknown relay response, status: {0}, body: [REDACTED]") + )] + UnknownRelayError(StatusCode, String), + #[error("Too many requests")] + TooManyRequests, + #[error("Connection error")] + ConnectionError, + #[error("Internal Error")] + InternalError, +} + +impl Debug for RelayError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl From for RelayError { + fn from(err: reqwest::Error) -> Self { + RelayError::RequestError(RedactableReqwestError(err)) + } +} + +#[derive(Error)] +pub struct RedactableReqwestError(reqwest::Error); + +impl From for RedactableReqwestError { + fn from(err: reqwest::Error) -> Self { + RedactableReqwestError(err) + } +} + +impl Display for RedactableReqwestError { + #[cfg(not(feature = "redact_sensitive"))] + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } + + #[cfg(feature = "redact_sensitive")] + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.0.is_builder() { + write!(f, "Redacted Reqwest Error: Builder") + } else if self.0.is_request() { + write!(f, "Redacted Reqwest Error: Request") + } else if self.0.is_redirect() { + write!(f, "Redacted Reqwest Error: Redirect") + } else if self.0.is_status() { + write!(f, "Redacted Reqwest Error: Status") + } else if self.0.is_body() { + write!(f, "Redacted Reqwest Error: Body") + } else if self.0.is_decode() { + write!(f, "Redacted Reqwest Error: Decode") + } else { + write!(f, "Redacted Reqwest Error") + } + } +} + +impl Debug for RedactableReqwestError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} + +#[derive(Error, Clone, Serialize, Deserialize)] +pub struct RedactableRelayErrorResponse { + pub code: Option, + pub message: String, +} + +impl std::fmt::Display for RedactableRelayErrorResponse { + #[cfg(not(feature = "redact_sensitive"))] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Relay error: (code: {}, message: {})", + self.code.unwrap_or_default(), + self.message + ) + } + + #[cfg(feature = "redact_sensitive")] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Relay error: (code: {}, message: [REDACTED])", + self.code.unwrap_or_default(), + ) + } +} + +impl Debug for RedactableRelayErrorResponse { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} diff --git a/crates/rbuilder/src/mev_boost/mod.rs b/crates/rbuilder/src/mev_boost/mod.rs index 5f0fa1ff..28a0d149 100644 --- a/crates/rbuilder/src/mev_boost/mod.rs +++ b/crates/rbuilder/src/mev_boost/mod.rs @@ -1,3 +1,4 @@ +mod error; pub mod fake_mev_boost_relay; pub mod rpc; pub mod sign_payload; @@ -16,9 +17,9 @@ use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; use ssz::Encode; use std::{io::Write, str::FromStr}; -use thiserror::Error; use url::Url; +pub use error::*; pub use sign_payload::*; const JSON_CONTENT_TYPE: &str = "application/json"; @@ -209,46 +210,11 @@ pub struct ValidatorRegistration { pub signature: Bytes, } -#[derive(Error, Debug)] -pub enum RelayError { - #[error("Request error: {0}")] - RequestError(#[from] reqwest::Error), - #[error("Header error")] - InvalidHeader, - #[error("Relay error: {0}")] - RelayError(#[from] RelayErrorResponse), - #[error("Unknown relay response, status: {0}, body: {1}")] - UnknownRelayError(StatusCode, String), - #[error("Too many requests")] - TooManyRequests, - #[error("Connection error")] - ConnectionError, - #[error("Internal Error")] - InternalError, -} - -#[derive(Error, Debug, Clone, Serialize, Deserialize)] -pub struct RelayErrorResponse { - code: Option, - message: String, -} - -impl std::fmt::Display for RelayErrorResponse { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Relay error: (code: {}, message: {})", - self.code.unwrap_or_default(), - self.message - ) - } -} - #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum RelayResponse { Ok(T), - Error(RelayErrorResponse), + Error(RedactableRelayErrorResponse), } /// Info about a registered validator selected as proposer for a slot. @@ -288,7 +254,7 @@ pub enum Error { TooManyProofs, } -#[derive(Debug, thiserror::Error)] +#[derive(thiserror::Error)] pub enum SubmitBlockErr { #[error("Relay error: {0}")] RelayError(#[from] RelayError), @@ -305,7 +271,14 @@ pub enum SubmitBlockErr { #[error("RPC conversion Error")] /// RPC validates the submissions (eg: limit of txs) much more that our model. RPCConversionError(Error), - #[error("RPC serialization failed {0}")] + #[cfg_attr( + not(feature = "redact_sensitive"), + error("RPC serialization failed: {0}") + )] + #[cfg_attr( + feature = "redact_sensitive", + error("RPC serialization failed: [REDACTED]") + )] RPCSerializationError(String), #[error("Invalid header")] InvalidHeader, @@ -313,6 +286,12 @@ pub enum SubmitBlockErr { BlockKnown, } +impl std::fmt::Debug for SubmitBlockErr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self) + } +} + // Data API impl RelayClient { async fn get_one_delivered_payload( @@ -507,7 +486,10 @@ impl RelayClient { builder = builder.headers(headers).body(Body::from(body_data)); - Ok(builder.send().await.map_err(RelayError::RequestError)?) + Ok(builder + .send() + .await + .map_err(|e| RelayError::RequestError(e.into()))?) } /// Submits the block (call_relay_submit_block) and processes some special errors. @@ -527,7 +509,10 @@ impl RelayClient { return Err(RelayError::ConnectionError.into()); } - let data = resp.bytes().await.map_err(RelayError::RequestError)?; + let data = resp + .bytes() + .await + .map_err(|e| RelayError::RequestError(e.into()))?; if status == StatusCode::OK && data.as_ref() == b"" { return Ok(()); diff --git a/crates/rbuilder/src/utils/mod.rs b/crates/rbuilder/src/utils/mod.rs index 77850abc..8483dffb 100644 --- a/crates/rbuilder/src/utils/mod.rs +++ b/crates/rbuilder/src/utils/mod.rs @@ -11,6 +11,7 @@ mod tx_signer; #[cfg(test)] pub mod test_utils; +pub mod tracing; use alloy_network::Ethereum; use alloy_primitives::{Sign, I256, U256}; diff --git a/crates/rbuilder/src/utils/tracing.rs b/crates/rbuilder/src/utils/tracing.rs new file mode 100644 index 00000000..a02d06f6 --- /dev/null +++ b/crates/rbuilder/src/utils/tracing.rs @@ -0,0 +1,15 @@ +/// Allows to call event! with level as a parameter (event! only allows constants as level parameter) +#[macro_export] +macro_rules! dynamic_event { + ($level:expr, $($arg:tt)+) => { + match $level { + Level::TRACE => event!(Level::TRACE, $($arg)+), + Level::DEBUG => event!(Level::DEBUG, $($arg)+), + Level::INFO => event!(Level::INFO, $($arg)+), + Level::WARN => event!(Level::WARN, $($arg)+), + Level::ERROR => event!(Level::ERROR, $($arg)+), + } + }; +} + +pub use dynamic_event; diff --git a/crates/rbuilder/src/validation_api_client.rs b/crates/rbuilder/src/validation_api_client.rs index f2eb53f5..797fbd40 100644 --- a/crates/rbuilder/src/validation_api_client.rs +++ b/crates/rbuilder/src/validation_api_client.rs @@ -1,11 +1,10 @@ use alloy_json_rpc::{ErrorPayload, RpcError}; -use std::sync::Arc; +use std::{fmt::Debug, sync::Arc}; use crate::{ mev_boost::SubmitBlockRequest, telemetry::add_block_validation_time, utils::{http_provider, BoxedProvider}, - validation_api_client::ValdationError::UnableToValidate, }; use alloy_primitives::B256; use alloy_provider::Provider; @@ -31,12 +30,26 @@ pub struct ValidationAPIClient { providers: Vec>, } -#[derive(Debug, thiserror::Error)] -pub enum ValdationError { - #[error("Unable to validate block: {0}")] - UnableToValidate(String), +#[derive(thiserror::Error)] +pub enum ValidationError { + #[error("No validation nodes")] + NoValidationNodes, + #[error("Failed to serialize request")] + FailedToSerializeRequest, + #[error("Failed to validate block, no valid responses from validation nodes")] + NoValidResponseFromValidationNodes, #[error("Validation failed")] ValidationFailed(ErrorPayload), + + #[cfg_attr(not(feature = "redact_sensitive"), error("Local usage error: {0}"))] + #[cfg_attr(feature = "redact_sensitive", error("Local usage error: [REDACTED]"))] + LocalUsageError(Box), +} + +impl Debug for ValidationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self) + } } impl ValidationAPIClient { @@ -55,10 +68,10 @@ impl ValidationAPIClient { withdrawals_root: B256, parent_beacon_block_root: Option, cancellation_token: CancellationToken, - ) -> Result<(), ValdationError> { + ) -> Result<(), ValidationError> { let start = std::time::Instant::now(); if self.providers.is_empty() { - return Err(UnableToValidate("No validation nodes".to_string())); + return Err(ValidationError::NoValidationNodes); } let method = match req { @@ -109,7 +122,7 @@ impl ValidationAPIClient { error!(err = ?err, "Validation node returned error"); // this should mean that block did not pass validation add_block_validation_time(start.elapsed()); - return Err(ValdationError::ValidationFailed(err)); + return Err(ValidationError::ValidationFailed(err)); } else { warn!(err = ?err, "Unable to validate block"); } @@ -117,7 +130,7 @@ impl ValidationAPIClient { Err(RpcError::SerError(err)) => { error!(err = ?err, "Serialization error"); // we will not recover from this error so no point for waiting for other responses - return Err(UnableToValidate("Failed to serialize request".to_string())); + return Err(ValidationError::FailedToSerializeRequest); } Err(RpcError::DeserError { err, text }) => { if !(text.contains("504 Gateway Time-out") || text.contains("502 Bad Gateway")) @@ -141,15 +154,13 @@ impl ValidationAPIClient { Err(RpcError::LocalUsageError(err)) => { error!(err = ?err, "Local usage error"); // we will not recover from this error so no point for waiting for other responses - return Err(UnableToValidate(format!("Local usage error: {:?}", err))); + return Err(ValidationError::LocalUsageError(err)); } } } // if we did not return by this point we did not validate block - Err(UnableToValidate( - "Failed to validate block, no valid responses from validation nodes".to_string(), - )) + Err(ValidationError::NoValidResponseFromValidationNodes) } } diff --git a/docs/LOGS_PRIVACY.md b/docs/LOGS_PRIVACY.md new file mode 100644 index 00000000..2f27b84d --- /dev/null +++ b/docs/LOGS_PRIVACY.md @@ -0,0 +1,90 @@ +# Logs Privacy in rbuilder + +## Introduction + +Log privacy in rbuilder refers to the level of data exposed in logs via macros like `error!`. A key principle in rbuilder is that we never log a full order, as this information could be harmful to the order sender. + +### Why is this important? + +- A non-landed order, if logged in full, could potentially be executed in a later block, causing losses for the order owner. +- Even if an order has built-in protections against unexpected executions, the order owner might still incur gas fees. + +## External Error Redaction + +While we don't log full orders ourselves, we sometimes interact with external systems and log their error codes. Since some of these may contain plain strings, we offer an option to redact any error before logging. + +### Enabling Error Redaction + +To enable external error redaction, use the `redact_sensitive` feature flag. + +### Example of Error Redaction + +**Never** derive `Display` or `Debug` for errors which may contain sensitive info. + +Instead, explicitly implement them using your favourite library, or manually. + +```rust +#[derive(Error)] +pub enum SomeError { + #[error("Request error: {0}")] + RequestError(#[from] RedactableReqwestError), + + #[cfg_attr( + not(feature = "redact_sensitive"), + error("Unknown relay response, status: {0}, body: {1}") + )] + #[cfg_attr( + feature = "redact_sensitive", + error("Unknown relay response, status: {0}, body: [REDACTED]") + )] + UnknownRelayError(StatusCode, String), + + #[error("Too many requests")] + TooManyRequests, + #[error("Connection error")] + ConnectionError, + #[error("Internal Error")] + InternalError, +} + +impl Debug for RelayError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self) + } +} + +#[derive(Error)] +pub struct RedactableReqwestError(reqwest::Error); + +impl Display for RedactableReqwestError { + #[cfg(not(feature = "redact_sensitive"))] + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } + + #[cfg(feature = "redact_sensitive")] + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.0.is_builder() { + write!(f, "Redacted Reqwest Error: Builder") + } else if self.0.is_request() { + write!(f, "Redacted Reqwest Error: Request") + } else if self.0.is_redirect() { + write!(f, "Redacted Reqwest Error: Redirect") + } else if self.0.is_status() { + write!(f, "Redacted Reqwest Error: Status") + } else if self.0.is_body() { + write!(f, "Redacted Reqwest Error: Body") + } else if self.0.is_decode() { + write!(f, "Redacted Reqwest Error: Decode") + } else { + write!(f, "Redacted Reqwest Error") + } + } +} + +impl Debug for RedactableReqwestError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(self, f) + } +} +``` From 6f40cfe808fd6719c7d3da9f808c81e32f0b51ed Mon Sep 17 00:00:00 2001 From: Robert Miller Date: Sat, 14 Sep 2024 17:45:36 -0400 Subject: [PATCH 11/30] Add sample Lighthouse config (#179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Just adding a snippet to the readme to help run rbuilder in live mode. ## 💡 Motivation and Context --- ## ✅ I have completed the following steps: * [ ] Run `make lint` * [ ] Run `make test` * [ ] Added tests (if applicable) --------- Co-authored-by: liamaharon --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 836a43bc..7f3f3cfa 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,27 @@ For more details on how to use rbuilder for backtesting, see https://github.com/ To run rbuilder you need: * Reth node for state. (`reth_datadir`) * Reth node must expose ipc interface for mempool tx subscription (`el_node_ipc_path`). -* CL node that triggers new payload events (it must be additionally configured to trigger payload event every single time) +* CL node that triggers new payload events (it must be additionally configured to trigger payload event every single time). * Source of bundles that sends `eth_sendBundle`, `mev_sendBundle`, `eth_sendRawTransaction` as JSON rpc calls. (`jsonrpc_server_port`) (by default rbuilder will take raw txs from the reth node mempool) * Relays so submit to (`relays`) * Alternatively it can submit to the block validation API if run in the dry run mode (`dry_run`, `dry_run_validation_url`) +A sample configuration for running Lighthouse and triggering payload events would be: +``` +./target/maxperf/lighthouse bn \ + --network mainnet \ + --execution-endpoint http://localhost:8551 \ + --execution-jwt /secrets/jwt.hex \ + --checkpoint-sync-url https://mainnet.checkpoint.sigp.io \ + --disable-deposit-contract-sync \ + --http \ + --http-port 3500 \ + --always-prepare-payload \ + --prepare-payload-lookahead 8000 \ + --suggested-fee-recipient 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 +``` + Additionally, you can: * configure block processor API as a sink for submitted blocks (`blocks_processor_url`) * setup Prometheus / Grafana for metrics (served on `telemetry_port` + `/debug/metrics/prometheus`) From 9873243ec5eec5a1476d67daae69689de4c74ba0 Mon Sep 17 00:00:00 2001 From: blessedstaff <86270019+blessedstaff@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:02:25 +0800 Subject: [PATCH 12/30] Add relay_secret_key in live example (#177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary `config-live-example.toml` file does not have RELAY_SECRET_KEY which is required to run rbuilder. added this to make example file easier to run. ## 💡 Motivation and Context Makes documentation clearer ## ✅ I have completed the following steps: * [x ] Run `make lint` * [x ] Run `make test` --------- Co-authored-by: Chris Hager --- config-live-example.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config-live-example.toml b/config-live-example.toml index 9aa3ce6f..2b6836b2 100644 --- a/config-live-example.toml +++ b/config-live-example.toml @@ -9,6 +9,8 @@ chain = "mainnet" reth_datadir = "/mnt/data/reth" coinbase_secret_key = "env:COINBASE_SECRET_KEY" +relay_secret_key = "env:RELAY_SECRET_KEY" +optimistic_relay_secret_key = "env:OPTIMISTIC_RELAY_SECRET_KEY" # cl_node_url can be a single value, array of values, or passed by an environment variables with values separated with a comma # cl_node_url = "http://localhost:3500" From 705c9b802078e91542b8223a428aa138f0dce307 Mon Sep 17 00:00:00 2001 From: Chris Hager Date: Wed, 18 Sep 2024 10:55:22 +0200 Subject: [PATCH 13/30] docs: reproducible builds (#181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Document reproducible builds in README --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [x] Added tests (if applicable) --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 7f3f3cfa..1f75e48d 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ It is designed to provide a delightful developer experience, enabling community - **Bundle merging**: bundles that target transactions which have already been included in a pending block can be dropped if they are marked in `reverting_tx_hashes`. - **Smart nonce management**: identifies and smartly handles nonce dependencies between bundles and transactions - **Using [Reth](https://github.com/paradigmxyz/reth/)**: leverages fast, efficient and user-friendly Ethereum node written in Rust +- Reproducible builds ## Running rbuilder @@ -101,6 +102,27 @@ You can query the local relay for proposed blocks like this: curl http://localhost:5555/relay/v1/data/bidtraces/proposer_payload_delivered ``` +### Reproducible builds + +You only need to set the `SOURCE_DATE_EPOCH` environment variable to ensure that the build is reproducible: + +```bash +# Use last commit timestamp as the build date +$ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) + +# build #1 +$ rm -rf target/ +$ cargo build --release +$ sha256sum target/release/rbuilder +d92ac33b94e16ed4a035b9dd52108fe78bd9bb160a91fced8e439f59b84c3207 target/release/rbuilder + +# build #2 +$ rm -rf target/ +$ cargo build --release +$ sha256sum target/release/rbuilder +d92ac33b94e16ed4a035b9dd52108fe78bd9bb160a91fced8e439f59b84c3207 target/release/rbuilder +``` + --- ## Release Stability and Development Process From 20b4f9368edeb658663c4cff02dd5e491fb1af1f Mon Sep 17 00:00:00 2001 From: nikoseven Date: Sat, 21 Sep 2024 01:54:49 +0800 Subject: [PATCH 14/30] feat: improve UsedStateEVMInspector by adding more op-codes (#161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Added support for SELFBALANCE, BALANCE, CALL, CREATE, and SELFDESTRUCT op-codes in UsedStateEVMInspector. New test cases for evm inspector have been added. ## 💡 Motivation and Context Related discussion in https://github.com/flashbots/rbuilder/issues/58. For opcodes like EXTCODECOPY, EXTCODEHASH, and EXTCODESIZE, I thought we could add them in the future with a concrete use case, so that we can properly design the datastruct for it. --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [x] Added tests (if applicable) --- crates/rbuilder/src/building/evm_inspector.rs | 149 +++++++++++++++-- .../src/building/testing/contracts.json | 5 +- .../testing/evm_inspector_tests/mod.rs | 155 ++++++++++++++++++ .../testing/evm_inspector_tests/setup.rs | 120 ++++++++++++++ crates/rbuilder/src/building/testing/mod.rs | 2 + .../src/building/testing/test_chain_state.rs | 46 +++++- mev-test-contract/Makefile | 2 +- mev-test-contract/src/MevTest.sol | 17 ++ 8 files changed, 471 insertions(+), 25 deletions(-) create mode 100644 crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs create mode 100644 crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs diff --git a/crates/rbuilder/src/building/evm_inspector.rs b/crates/rbuilder/src/building/evm_inspector.rs index 42e2bbf6..84ca16ba 100644 --- a/crates/rbuilder/src/building/evm_inspector.rs +++ b/crates/rbuilder/src/building/evm_inspector.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use alloy_primitives::{Address, B256, U256}; use reth_primitives::TransactionSignedEcRecovered; use revm::{ - interpreter::{opcode, Interpreter}, + interpreter::{opcode, CallInputs, CallOutcome, Interpreter}, Database, EvmContext, Inspector, }; use revm_inspectors::access_list::AccessListInspector; @@ -19,19 +19,33 @@ pub struct UsedStateTrace { pub read_slot_values: HashMap, /// write slot values contains last write pub written_slot_values: HashMap, + /// balance of first read + pub read_balances: HashMap, + /// number of `wei` sent or received during execution + pub received_amount: HashMap, + pub sent_amount: HashMap, + pub created_contracts: Vec
, + pub destructed_contracts: Vec
, +} + +#[derive(Debug, Clone, Default)] +enum NextStepAction { + #[default] + None, + ReadSloadKeyResult(B256), + ReadBalanceResult(Address), } #[derive(Debug)] struct UsedStateEVMInspector<'a> { - // if previous instruction was sload we store key that was used to call sload here - tmp_sload_key: Option, + next_step_action: NextStepAction, used_state_trace: &'a mut UsedStateTrace, } impl<'a> UsedStateEVMInspector<'a> { fn new(used_state_trace: &'a mut UsedStateTrace) -> Self { Self { - tmp_sload_key: None, + next_step_action: NextStepAction::None, used_state_trace, } } @@ -62,25 +76,35 @@ where DB: Database, { fn step(&mut self, interpreter: &mut Interpreter, _: &mut EvmContext) { - if let Some(slot) = self.tmp_sload_key.take() { - if let Ok(value) = interpreter.stack.peek(0) { - let value = B256::from(value.to_be_bytes()); - let key = SlotKey { - address: interpreter.contract.target_address, - key: slot, - }; - self.used_state_trace - .read_slot_values - .entry(key) - .or_insert(value); + match std::mem::take(&mut self.next_step_action) { + NextStepAction::ReadSloadKeyResult(slot) => { + if let Ok(value) = interpreter.stack.peek(0) { + let value = B256::from(value.to_be_bytes()); + let key = SlotKey { + address: interpreter.contract.target_address, + key: slot, + }; + self.used_state_trace + .read_slot_values + .entry(key) + .or_insert(value); + } + } + NextStepAction::ReadBalanceResult(addr) => { + if let Ok(value) = interpreter.stack.peek(0) { + self.used_state_trace + .read_balances + .entry(addr) + .or_insert(value); + } } + NextStepAction::None => {} } - match interpreter.current_opcode() { opcode::SLOAD => { if let Ok(slot) = interpreter.stack().peek(0) { let slot = B256::from(slot.to_be_bytes()); - self.tmp_sload_key = Some(slot); + self.next_step_action = NextStepAction::ReadSloadKeyResult(slot); } } opcode::SSTORE => { @@ -104,9 +128,65 @@ where .insert(key, written_value); } } + opcode::BALANCE => { + if let Ok(addr) = interpreter.stack().peek(0) { + let addr = Address::from_word(B256::from(addr.to_be_bytes())); + self.next_step_action = NextStepAction::ReadBalanceResult(addr); + } + } + opcode::SELFBALANCE => { + let addr = interpreter.contract().target_address; + self.next_step_action = NextStepAction::ReadBalanceResult(addr); + } _ => (), } } + + fn call(&mut self, _: &mut EvmContext, inputs: &mut CallInputs) -> Option { + if let Some(transfer_value) = inputs.transfer_value() { + if !transfer_value.is_zero() { + *self + .used_state_trace + .sent_amount + .entry(inputs.transfer_from()) + .or_default() += transfer_value; + *self + .used_state_trace + .received_amount + .entry(inputs.transfer_to()) + .or_default() += transfer_value; + } + } + None + } + + fn create_end( + &mut self, + _: &mut EvmContext, + _: &revm::interpreter::CreateInputs, + outcome: revm::interpreter::CreateOutcome, + ) -> revm::interpreter::CreateOutcome { + if let Some(addr) = outcome.address { + self.used_state_trace.created_contracts.push(addr); + } + outcome + } + + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + self.used_state_trace.destructed_contracts.push(contract); + if !value.is_zero() { + *self + .used_state_trace + .sent_amount + .entry(contract) + .or_default() += value; + *self + .used_state_trace + .received_amount + .entry(target) + .or_default() += value; + } + } } #[derive(Debug)] @@ -148,6 +228,7 @@ impl<'a> RBuilderEVMInspector<'a> { impl<'a, DB> Inspector for RBuilderEVMInspector<'a> where DB: Database, + UsedStateEVMInspector<'a>: Inspector, { #[inline] fn step(&mut self, interp: &mut Interpreter, data: &mut EvmContext) { @@ -156,4 +237,38 @@ where used_state_inspector.step(interp, data); } } + + #[inline] + fn call( + &mut self, + context: &mut EvmContext, + inputs: &mut CallInputs, + ) -> Option { + if let Some(used_state_inspector) = &mut self.used_state_inspector { + used_state_inspector.call(context, inputs) + } else { + None + } + } + + #[inline] + fn create_end( + &mut self, + context: &mut EvmContext, + inputs: &revm::interpreter::CreateInputs, + outcome: revm::interpreter::CreateOutcome, + ) -> revm::interpreter::CreateOutcome { + if let Some(used_state_inspector) = &mut self.used_state_inspector { + used_state_inspector.create_end(context, inputs, outcome) + } else { + outcome + } + } + + #[inline] + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + if let Some(used_state_inspector) = &mut self.used_state_inspector { + used_state_inspector.selfdestruct(contract, target, value) + } + } } diff --git a/crates/rbuilder/src/building/testing/contracts.json b/crates/rbuilder/src/building/testing/contracts.json index e49ddcee..7816e7bd 100644 --- a/crates/rbuilder/src/building/testing/contracts.json +++ b/crates/rbuilder/src/building/testing/contracts.json @@ -1,3 +1,4 @@ { - "MevTest": "0x6080604052600436106100345760003560e01c80634988880a14610039578063e6d252451461004e578063f9da581d14610061575b600080fd5b61004c610047366004610172565b610069565b005b61004c61005c366004610194565b61010a565b61004c610143565b81548181146100be5760405162461bcd60e51b815260206004820152601860248201527f4f6c642076616c756520646f6573206e6f74206d617463680000000000000000604482015260640160405180910390fd5b60006100cb8360016101c4565b808555905034156101045760405141903480156108fc02916000818181858888f19350505050158015610102573d6000803e3d6000fd5b505b50505050565b6040516001600160a01b038216903480156108fc02916000818181858888f1935050505015801561013f573d6000803e3d6000fd5b5050565b60405141903480156108fc02916000818181858888f1935050505015801561016f573d6000803e3d6000fd5b50565b6000806040838503121561018557600080fd5b50508035926020909101359150565b6000602082840312156101a657600080fd5b81356001600160a01b03811681146101bd57600080fd5b9392505050565b808201808211156101e557634e487b7160e01b600052601160045260246000fd5b9291505056fea2646970667358221220d7381ca961d18784470880695e0cf6be236e0d7b1e13ae4415c677fb898717a064736f6c63430008150033" -} \ No newline at end of file + "MevTest": "0x6080604052600436106100555760003560e01c80634988880a1461005a5780637da3c3ab1461006f578063d6782ec714610077578063e6d252451461008a578063f9711c221461009d578063f9da581d146100b0575b600080fd5b61006d61006836600461027b565b6100b8565b005b61006d610159565b61006d61008536600461029d565b610163565b61006d61009836600461029d565b61017b565b61006d6100ab36600461029d565b6101b0565b61006d610240565b815481811461010d5760405162461bcd60e51b815260206004820152601860248201527f4f6c642076616c756520646f6573206e6f74206d617463680000000000000000604482015260640160405180910390fd5b600061011a8360016102cd565b808555905034156101535760405141903480156108fc02916000818181858888f19350505050158015610151573d6000803e3d6000fd5b505b50505050565b610161610159565b565b6101776001600160a01b03821631476102cd565b5050565b6040516001600160a01b038216903480156108fc02916000818181858888f19350505050158015610177573d6000803e3d6000fd5b60006040516101be9061026f565b604051809103906000f0801580156101da573d6000803e3d6000fd5b50604051631beb261560e01b81526001600160a01b03848116600483015291925090821690631beb26159034906024016000604051808303818588803b15801561022357600080fd5b505af1158015610237573d6000803e3d6000fd5b50505050505050565b60405141903480156108fc02916000818181858888f1935050505015801561026c573d6000803e3d6000fd5b50565b60bf806102f583390190565b6000806040838503121561028e57600080fd5b50508035926020909101359150565b6000602082840312156102af57600080fd5b81356001600160a01b03811681146102c657600080fd5b9392505050565b808201808211156102ee57634e487b7160e01b600052601160045260246000fd5b9291505056fe6080604052348015600f57600080fd5b5060a280601d6000396000f3fe608060405260043610601c5760003560e01c80631beb2615146021575b600080fd5b6030602c366004603e565b6032565b005b806001600160a01b0316ff5b600060208284031215604f57600080fd5b81356001600160a01b0381168114606557600080fd5b939250505056fea26469706673582212207422a0f368426edbe9d06fc472e76995dc7edc7b9e20673c4ab45757ae32f30064736f6c634300081a0033a26469706673582212201b4bf34a5948cd633421a6c6648a0db2ec7df1d12ccf2973d2cf78dd6b5775e464736f6c634300081a0033", + "MevTestInitBytecode": "0x6080604052348015600f57600080fd5b506103e98061001f6000396000f3fe6080604052600436106100555760003560e01c80634988880a1461005a5780637da3c3ab1461006f578063d6782ec714610077578063e6d252451461008a578063f9711c221461009d578063f9da581d146100b0575b600080fd5b61006d61006836600461027b565b6100b8565b005b61006d610159565b61006d61008536600461029d565b610163565b61006d61009836600461029d565b61017b565b61006d6100ab36600461029d565b6101b0565b61006d610240565b815481811461010d5760405162461bcd60e51b815260206004820152601860248201527f4f6c642076616c756520646f6573206e6f74206d617463680000000000000000604482015260640160405180910390fd5b600061011a8360016102cd565b808555905034156101535760405141903480156108fc02916000818181858888f19350505050158015610151573d6000803e3d6000fd5b505b50505050565b610161610159565b565b6101776001600160a01b03821631476102cd565b5050565b6040516001600160a01b038216903480156108fc02916000818181858888f19350505050158015610177573d6000803e3d6000fd5b60006040516101be9061026f565b604051809103906000f0801580156101da573d6000803e3d6000fd5b50604051631beb261560e01b81526001600160a01b03848116600483015291925090821690631beb26159034906024016000604051808303818588803b15801561022357600080fd5b505af1158015610237573d6000803e3d6000fd5b50505050505050565b60405141903480156108fc02916000818181858888f1935050505015801561026c573d6000803e3d6000fd5b50565b60bf806102f583390190565b6000806040838503121561028e57600080fd5b50508035926020909101359150565b6000602082840312156102af57600080fd5b81356001600160a01b03811681146102c657600080fd5b9392505050565b808201808211156102ee57634e487b7160e01b600052601160045260246000fd5b9291505056fe6080604052348015600f57600080fd5b5060a280601d6000396000f3fe608060405260043610601c5760003560e01c80631beb2615146021575b600080fd5b6030602c366004603e565b6032565b005b806001600160a01b0316ff5b600060208284031215604f57600080fd5b81356001600160a01b0381168114606557600080fd5b939250505056fea26469706673582212207422a0f368426edbe9d06fc472e76995dc7edc7b9e20673c4ab45757ae32f30064736f6c634300081a0033a26469706673582212201b4bf34a5948cd633421a6c6648a0db2ec7df1d12ccf2973d2cf78dd6b5775e464736f6c634300081a0033" +} diff --git a/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs b/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs new file mode 100644 index 00000000..49b9a857 --- /dev/null +++ b/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs @@ -0,0 +1,155 @@ +use alloy_primitives::{B256, U256}; + +use crate::building::{ + evm_inspector::SlotKey, + testing::{evm_inspector_tests::setup::TestSetup, test_chain_state::NamedAddr}, +}; + +pub mod setup; + +#[test] +fn test_transfer() -> eyre::Result<()> { + let test_setup = TestSetup::new()?; + + let sender = NamedAddr::User(1); + let receiver = NamedAddr::User(2); + let transfer_value = 10000; + + let tx = test_setup.make_transfer_tx(sender, receiver, transfer_value)?; + let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; + + // check sent_amount/received_amount + let sender_addr = test_setup.named_address(sender)?; + let receiver_addr = test_setup.named_address(receiver)?; + assert_eq!(used_state_trace.received_amount.len(), 1); + assert_eq!( + used_state_trace.received_amount.get(&receiver_addr), + Some(&U256::from(transfer_value)) + ); + assert_eq!(used_state_trace.sent_amount.len(), 1); + assert_eq!( + used_state_trace.sent_amount.get(&sender_addr), + Some(&U256::from(transfer_value)) + ); + + // check read_slot_values/written_slot_values + let sender_nonce_slot_key = SlotKey { + address: sender_addr, + key: B256::ZERO, + }; + assert_eq!(used_state_trace.read_slot_values.len(), 1); + assert_eq!(used_state_trace.written_slot_values.len(), 1); + let nonce_read_value = used_state_trace + .read_slot_values + .get(&sender_nonce_slot_key); + let nonce_written_value = used_state_trace + .written_slot_values + .get(&sender_nonce_slot_key); + assert!(nonce_read_value.is_some()); + assert!(nonce_written_value.is_some()); + let nonce_read_value: U256 = nonce_read_value.unwrap().clone().into(); + let nonce_written_value: U256 = nonce_written_value.unwrap().clone().into(); + assert_eq!( + nonce_written_value.checked_sub(nonce_read_value), + Some(U256::from(1)) + ); + + // check created_contracts/destructed_contracts + assert!(used_state_trace.created_contracts.is_empty()); + assert!(used_state_trace.destructed_contracts.is_empty()); + + Ok(()) +} + +#[test] +fn test_call_contract() -> eyre::Result<()> { + let test_setup = TestSetup::new()?; + + let tx = test_setup.make_increment_value_tx(100, 0)?; + let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; + + let test_contract_addr = test_setup.test_contract_address()?; + let slot_key = SlotKey { + address: test_contract_addr, + key: B256::from(U256::from(100)), + }; + assert_eq!( + used_state_trace.read_slot_values.get(&slot_key), + Some(&B256::from(U256::from(0))) + ); + assert_eq!( + used_state_trace.written_slot_values.get(&slot_key), + Some(&B256::from(U256::from(1))) + ); + + Ok(()) +} + +#[test] +fn test_deploy_contract() -> eyre::Result<()> { + let test_setup = TestSetup::new()?; + + let tx = test_setup.make_deploy_mev_test_tx()?; + let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; + + assert_eq!(used_state_trace.created_contracts.len(), 1); + + Ok(()) +} + +#[test] +fn test_read_balance() -> eyre::Result<()> { + let test_setup = TestSetup::new()?; + + let mev_test_contract_addr = test_setup.named_address(NamedAddr::MevTest)?; + let dummy_addr = test_setup.named_address(NamedAddr::Dummy)?; + let tx: reth_primitives::TransactionSignedEcRecovered = + test_setup.make_test_read_balance_tx(dummy_addr, 100)?; + let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; + + assert_eq!(used_state_trace.read_balances.len(), 2); + assert_eq!( + used_state_trace.read_balances.get(&dummy_addr), + Some(&U256::from(0)) + ); + assert_eq!( + used_state_trace.read_balances.get(&mev_test_contract_addr), + Some(&U256::from(100)) + ); + + Ok(()) +} + +#[test] +fn test_ephemeral_contract_destruct() -> eyre::Result<()> { + let test_setup = TestSetup::new()?; + + let refund_addr = test_setup.named_address(NamedAddr::Dummy)?; + let tx: reth_primitives::TransactionSignedEcRecovered = + test_setup.make_test_ephemeral_contract_destruct_tx(refund_addr, 100)?; + let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; + + assert_eq!(used_state_trace.created_contracts.len(), 1); + assert_eq!(used_state_trace.destructed_contracts.len(), 1); + assert_eq!( + used_state_trace.created_contracts[0], + used_state_trace.destructed_contracts[0] + ); + let ephemeral_contract_addr = used_state_trace.created_contracts[0]; + assert_eq!( + used_state_trace + .received_amount + .get(&ephemeral_contract_addr), + Some(&U256::from(100)) + ); + assert_eq!( + used_state_trace.sent_amount.get(&ephemeral_contract_addr), + Some(&U256::from(100)) + ); + assert_eq!( + used_state_trace.received_amount.get(&refund_addr), + Some(&U256::from(100)) + ); + + Ok(()) +} diff --git a/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs b/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs new file mode 100644 index 00000000..2d503dcc --- /dev/null +++ b/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs @@ -0,0 +1,120 @@ +use reth_primitives::{transaction::FillTxEnv, Address, TransactionSignedEcRecovered}; +use revm::{inspector_handle_register, primitives::Env}; +use revm_primitives::TxEnv; + +use crate::building::{ + evm_inspector::{RBuilderEVMInspector, UsedStateTrace}, + testing::test_chain_state::{BlockArgs, NamedAddr, TestChainState, TestContracts, TxArgs}, + BlockState, +}; + +#[derive(Debug)] +pub struct TestSetup { + test_chain: TestChainState, +} + +impl TestSetup { + pub fn new() -> eyre::Result { + Ok(Self { + test_chain: TestChainState::new(BlockArgs::default())?, + }) + } + + pub fn named_address(&self, named_addr: NamedAddr) -> eyre::Result
{ + self.test_chain.named_address(named_addr) + } + + pub fn test_contract_address(&self) -> eyre::Result
{ + self.test_chain.named_address(NamedAddr::MevTest) + } + + pub fn make_transfer_tx( + &self, + from: NamedAddr, + to: NamedAddr, + value: u64, + ) -> eyre::Result { + let tx_args = TxArgs::new(from, 0).to(to).value(value); + let tx = self.test_chain.sign_tx(tx_args)?; + Ok(tx) + } + + pub fn make_increment_value_tx( + &self, + slot: u64, + current_value: u64, + ) -> eyre::Result { + let tx_args = TxArgs::new_increment_value(NamedAddr::User(0), 0, slot, current_value); + let tx = self.test_chain.sign_tx(tx_args)?; + Ok(tx) + } + + pub fn make_deploy_mev_test_tx(&self) -> eyre::Result { + let mev_test_init_bytecode = TestContracts::load().mev_test_init_bytecode; + let tx_args = TxArgs::new(NamedAddr::User(0), 0).input(mev_test_init_bytecode.into()); + let tx = self.test_chain.sign_tx(tx_args)?; + Ok(tx) + } + + pub fn make_test_read_balance_tx( + &self, + read_balance_addr: Address, + value: u64, + ) -> eyre::Result { + let tx_args = + TxArgs::new_test_read_balance(NamedAddr::User(0), 0, read_balance_addr, value); + let tx = self.test_chain.sign_tx(tx_args)?; + Ok(tx) + } + + pub fn make_test_ephemeral_contract_destruct_tx( + &self, + refund_addr: Address, + value: u64, + ) -> eyre::Result { + let tx_args = + TxArgs::new_test_ephemeral_contract_destruct(NamedAddr::User(0), 0, refund_addr) + .value(value); + let tx = self.test_chain.sign_tx(tx_args)?; + Ok(tx) + } + + pub fn inspect_tx_without_commit( + &self, + tx: TransactionSignedEcRecovered, + ) -> eyre::Result { + let mut used_state_trace = UsedStateTrace::default(); + let mut inspector = RBuilderEVMInspector::new(&tx, Some(&mut used_state_trace)); + + // block state + let state_provider = self.test_chain.provider_factory().latest()?; + let mut block_state = BlockState::new(state_provider); + let mut db_ref = block_state.new_db_ref(); + + // execute transaction + { + let mut tx_env = TxEnv::default(); + tx.as_ref().fill_tx_env(&mut tx_env, tx.signer()); + let mut evm = revm::Evm::builder() + .with_spec_id(self.test_chain.block_building_context().spec_id) + .with_env(Box::new(Env { + cfg: self + .test_chain + .block_building_context() + .initialized_cfg + .cfg_env + .clone(), + block: self.test_chain.block_building_context().block_env.clone(), + tx: tx_env, + })) + .with_external_context(&mut inspector) + .with_db(db_ref.as_mut()) + .append_handler_register(inspector_handle_register) + .build(); + evm.transact() + .map_err(|e| eyre::eyre!("execution failure: {:?}", e))?; + } + + Ok(used_state_trace) + } +} diff --git a/crates/rbuilder/src/building/testing/mod.rs b/crates/rbuilder/src/building/testing/mod.rs index f442a8ef..38c64989 100644 --- a/crates/rbuilder/src/building/testing/mod.rs +++ b/crates/rbuilder/src/building/testing/mod.rs @@ -1,3 +1,5 @@ #[cfg(test)] pub mod bundle_tests; +#[cfg(test)] +pub mod evm_inspector_tests; pub mod test_chain_state; diff --git a/crates/rbuilder/src/building/testing/test_chain_state.rs b/crates/rbuilder/src/building/testing/test_chain_state.rs index 98dd2b1f..50832b8f 100644 --- a/crates/rbuilder/src/building/testing/test_chain_state.rs +++ b/crates/rbuilder/src/building/testing/test_chain_state.rs @@ -174,9 +174,10 @@ impl TestChainState { gas_limit: args.gas_limit, max_fee_per_gas: args.max_fee_per_gas, max_priority_fee_per_gas: args.max_priority_fee, - to: TransactionKind::Call( - self.named_address(args.to.ok_or_else(|| eyre::eyre!("missing to address"))?)?, - ), + to: match args.to { + Some(named_addr) => TransactionKind::Call(self.named_address(named_addr)?), + None => TransactionKind::Create, + }, value: U256::from(args.value), access_list: Default::default(), input: args.input.into(), @@ -392,6 +393,35 @@ impl TxArgs { .value(value) } + /// This transaction for test purpose only, it reads balance of addr and the contract + pub fn new_test_read_balance(from: NamedAddr, nonce: u64, addr: Address, value: u64) -> Self { + Self::new(from, nonce) + .to(NamedAddr::MevTest) + .input( + [ + (*TEST_READ_BALANCE).into(), + B256::left_padding_from(addr.as_slice()).to_vec(), + ] + .concat(), + ) + .value(value) + } + + /// This transaction for test purpose only, it deploys a contract and let it selfdestruct within the tx. + pub fn new_test_ephemeral_contract_destruct( + from: NamedAddr, + nonce: u64, + refund_addr: Address, + ) -> Self { + Self::new(from, nonce).to(NamedAddr::MevTest).input( + [ + (*TEST_EPHEMERAL_CONTRACT_DESTRUCT).into(), + B256::left_padding_from(refund_addr.as_slice()).to_vec(), + ] + .concat(), + ) + } + pub fn to(self, to: NamedAddr) -> Self { Self { to: Some(to), @@ -434,9 +464,12 @@ impl TxArgs { static TEST_CONTRACTS: &str = include_str!("./contracts.json"); #[derive(Debug, serde::Deserialize)] -struct TestContracts { +pub struct TestContracts { #[serde(rename = "MevTest")] mev_test: Bytes, + + #[serde(rename = "MevTestInitBytecode")] + pub mev_test_init_bytecode: Bytes, } fn selector(func_signature: &str) -> [u8; 4] { @@ -449,10 +482,13 @@ lazy_static! { static ref SENT_TO_SELECTOR: [u8; 4] = selector("sendTo(address)"); static ref SEND_TO_COINBASE_SELECTOR: [u8; 4] = selector("sendToCoinbase()"); static ref REVERT_SELECTOR: [u8; 4] = selector("revert()"); + static ref TEST_READ_BALANCE: [u8; 4] = selector("testReadBalance(address)"); + static ref TEST_EPHEMERAL_CONTRACT_DESTRUCT: [u8; 4] = + selector("testEphemeralContractDestruct(address)"); } impl TestContracts { - fn load() -> Self { + pub fn load() -> Self { serde_json::from_str(TEST_CONTRACTS).expect("failed to load test contracts") } diff --git a/mev-test-contract/Makefile b/mev-test-contract/Makefile index 42582ab0..29ca84e6 100644 --- a/mev-test-contract/Makefile +++ b/mev-test-contract/Makefile @@ -11,7 +11,7 @@ build: init forge build update: build - cat out/MevTest.sol/MevTest.json | jq '{ "MevTest": .deployedBytecode.object }' > ../crates/rbuilder/src/building/bundle_tests/contracts.json + cat out/MevTest.sol/MevTest.json | jq '{ "MevTest": .deployedBytecode.object, "MevTestInitBytecode": .bytecode.object }' > ../crates/rbuilder/src/building/testing/contracts.json printSelectors: build forge in MevTest methodIdentifiers diff --git a/mev-test-contract/src/MevTest.sol b/mev-test-contract/src/MevTest.sol index 0fd3eed5..54a371e1 100644 --- a/mev-test-contract/src/MevTest.sol +++ b/mev-test-contract/src/MevTest.sol @@ -1,6 +1,12 @@ // SPDX-License-Identifier: Unlicense pragma solidity ^0.8.13; +contract EphemeralContractTest { + function destruct(address payable refundAddr) payable public { + selfdestruct(refundAddr); + } +} + contract MevTest { /// Sends all value to coinbase. @@ -36,4 +42,15 @@ contract MevTest { function revert() public payable { revert(); } + + /// Return sum of the contract's balance and addr's balanace, for testing evm inspector with selfbalance/balance opcode. + function testReadBalance(address payable addr) public payable { + address(this).balance + addr.balance; + } + + // Deploy a contract and let the contract self-destruct, for testing evm inspector on contract depoly and destruct. + function testEphemeralContractDestruct(address payable refund) public payable { + EphemeralContractTest ephemeral_contract = new EphemeralContractTest(); + ephemeral_contract.destruct{value: msg.value}(refund); + } } From 900aa724583e7331d3a64004b6b9f93007f039e7 Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Sat, 21 Sep 2024 11:29:26 +0200 Subject: [PATCH 15/30] Add comment to used state trace (#185) Adds comments from here https://github.com/flashbots/rbuilder/pull/161 --- crates/rbuilder/src/building/evm_inspector.rs | 11 +++++++++++ .../src/building/testing/evm_inspector_tests/mod.rs | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/rbuilder/src/building/evm_inspector.rs b/crates/rbuilder/src/building/evm_inspector.rs index 84ca16ba..073c5889 100644 --- a/crates/rbuilder/src/building/evm_inspector.rs +++ b/crates/rbuilder/src/building/evm_inspector.rs @@ -14,6 +14,9 @@ pub struct SlotKey { } #[derive(Debug, Clone, Default, PartialEq, Eq)] +/// UsedStateTrace is an execution trace of the given order +/// Limitations: +/// * `written_slot_values`, `received_amount` and `sent_amount` are not correct if transaction reverts pub struct UsedStateTrace { /// read slot values contains first read pub read_slot_values: HashMap, @@ -173,6 +176,14 @@ where } fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + // selfdestruct can be called multiple times during transaction execution + if self + .used_state_trace + .destructed_contracts + .contains(&contract) + { + return; + } self.used_state_trace.destructed_contracts.push(contract); if !value.is_zero() { *self diff --git a/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs b/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs index 49b9a857..858e9ad7 100644 --- a/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs +++ b/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs @@ -47,8 +47,8 @@ fn test_transfer() -> eyre::Result<()> { .get(&sender_nonce_slot_key); assert!(nonce_read_value.is_some()); assert!(nonce_written_value.is_some()); - let nonce_read_value: U256 = nonce_read_value.unwrap().clone().into(); - let nonce_written_value: U256 = nonce_written_value.unwrap().clone().into(); + let nonce_read_value: U256 = (*nonce_read_value.unwrap()).into(); + let nonce_written_value: U256 = (*nonce_written_value.unwrap()).into(); assert_eq!( nonce_written_value.checked_sub(nonce_read_value), Some(U256::from(1)) From 0ac5cf113953025b4a618e409125032f2f322ef4 Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Tue, 24 Sep 2024 19:38:04 +0200 Subject: [PATCH 16/30] Sparse trie (#174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Faster root hash This pr introduces option to use sparse merkle trie implementation for the root hash calculation. This implementation fetches relevant pieces of the trie into memory making subsequent root hash calculations faster. On my PC reference implementation takes about 150ms to calculate hash and the new one when everything is prefetched around 5ms. Fetching proof for data for one uncached account takes about 0.25ms. There are things to improve in implementation itself but the basic interface for the integration into the builder will be the same. ## debug-bench-machine This PR also redoes debug-bench-machine. Now you need to stop reth node and provide external rpc for it to work. The reason is that reth has trie only for the last block. Previous implementation used last block to generate changes and it applied that changes to the trie after the last block. Trie would already have these changes but default reth root hash does not care about that discrepancy and it would evaluate anyway, this was used as a hack to benchmark trie even though it would give incorrect results. Sparse trie implemenation would not work like that because it would detect errors such as removing key that was already removed from the trie. The benefit of this is that we can actually check correctness of the root hash on historical block. --- ## ✅ I have completed the following steps: * [ ] Run `make lint` * [ ] Run `make test` * [ ] Added tests (if applicable) --- Cargo.lock | 28 +++ crates/rbuilder/Cargo.toml | 2 + .../resim_landed_block.rs | 41 +--- .../rbuilder/src/bin/debug-bench-machine.rs | 207 +++++++++--------- crates/rbuilder/src/bin/dummy-builder.rs | 4 +- .../builders/block_building_helper.rs | 10 +- crates/rbuilder/src/building/builders/mod.rs | 2 + .../src/building/builders/ordering_builder.rs | 24 +- crates/rbuilder/src/building/mod.rs | 13 +- .../rbuilder/src/live_builder/base_config.rs | 19 ++ crates/rbuilder/src/live_builder/config.rs | 15 +- crates/rbuilder/src/roothash/mod.rs | 83 ++++++- crates/rbuilder/src/utils/mod.rs | 49 ++++- 13 files changed, 317 insertions(+), 180 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84ed2ac7..fb1aa429 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2825,6 +2825,33 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "eth-sparse-mpt" +version = "0.1.0" +source = "git+https://github.com/flashbots/eth-sparse-mpt?rev=664759b#664759b53d92e64d9a2e902100691b7ff4945ece" +dependencies = [ + "alloy-primitives 0.8.0", + "alloy-rlp", + "alloy-trie", + "hash-db", + "rayon", + "reth-db-api", + "reth-errors", + "reth-execution-errors", + "reth-provider", + "reth-trie", + "reth-trie-db", + "revm", + "revm-primitives", + "rustc-hash 2.0.0", + "serde", + "serde_json", + "serde_with", + "smallvec", + "thiserror", + "triehash", +] + [[package]] name = "ethabi" version = "18.0.0" @@ -7000,6 +7027,7 @@ dependencies = [ "csv", "ctor", "derivative", + "eth-sparse-mpt", "ethereum-consensus", "ethereum_ssz", "ethereum_ssz_derive", diff --git a/crates/rbuilder/Cargo.toml b/crates/rbuilder/Cargo.toml index bf0d29cf..4f7b9490 100644 --- a/crates/rbuilder/Cargo.toml +++ b/crates/rbuilder/Cargo.toml @@ -124,6 +124,8 @@ mockall = "0.12.1" shellexpand = "3.1.0" async-trait = "0.1.80" +eth-sparse-mpt = { git = "https://github.com/flashbots/eth-sparse-mpt", rev = "664759b" } + [build-dependencies] built = { version = "0.7.1", features = ["git2", "chrono"] } diff --git a/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs b/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs index 051cbf70..bffbdf4f 100644 --- a/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs +++ b/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs @@ -1,13 +1,10 @@ use crate::building::evm_inspector::SlotKey; use crate::building::tracers::AccumulatorSimulationTracer; use crate::building::{BlockBuildingContext, BlockState, PartialBlock, PartialBlockFork}; -use crate::primitives::serialize::{RawTx, TxEncoding}; -use crate::primitives::TransactionSignedEcRecoveredWithBlobs; use crate::utils::signed_uint_delta; +use crate::utils::{extract_onchain_block_txs, find_suggested_fee_recipient}; use ahash::{HashMap, HashSet}; -use alloy_consensus::TxEnvelope; -use alloy_eips::eip2718::Encodable2718; -use alloy_primitives::{Address, B256, I256}; +use alloy_primitives::{B256, I256}; use eyre::Context; use reth_chainspec::ChainSpec; use reth_db::DatabaseEnv; @@ -113,37 +110,3 @@ pub fn sim_historical_block( Ok(results) } - -fn find_suggested_fee_recipient( - block: &alloy_rpc_types::Block, - txs: &[TransactionSignedEcRecoveredWithBlobs], -) -> Address { - let coinbase = block.header.miner; - let (last_tx_signer, last_tx_to) = if let Some((signer, to)) = txs - .last() - .map(|tx| (tx.signer(), tx.to().unwrap_or_default())) - { - (signer, to) - } else { - return coinbase; - }; - - if last_tx_signer == coinbase { - last_tx_to - } else { - coinbase - } -} - -fn extract_onchain_block_txs( - onchain_block: &alloy_rpc_types::Block, -) -> eyre::Result> { - let mut result = Vec::new(); - for tx in onchain_block.transactions.clone().into_transactions() { - let tx_envelope: TxEnvelope = tx.try_into()?; - let encoded = tx_envelope.encoded_2718(); - let tx = RawTx { tx: encoded.into() }.decode(TxEncoding::NoBlobData)?; - result.push(tx.tx_with_blobs); - } - Ok(result) -} diff --git a/crates/rbuilder/src/bin/debug-bench-machine.rs b/crates/rbuilder/src/bin/debug-bench-machine.rs index 4eeae1c6..f2cc7584 100644 --- a/crates/rbuilder/src/bin/debug-bench-machine.rs +++ b/crates/rbuilder/src/bin/debug-bench-machine.rs @@ -1,31 +1,33 @@ //! App to benchmark/test the tx block execution. -//! It loads the last landed block and re-executes all the txs in it. -use alloy_primitives::{B256, U256}; +//! This only works when reth node is stopped and the chain moved forward form its synced state +//! It downloads block aftre the last one synced and re-executes all the txs in it. +use alloy_provider::Provider; use clap::Parser; +use eyre::Context; use itertools::Itertools; use rbuilder::{ - building::{ - sim::simulate_all_orders_with_sim_tree, BlockBuildingContext, BlockState, PartialBlock, - }, + building::{BlockBuildingContext, BlockState, PartialBlock, PartialBlockFork}, live_builder::{base_config::load_config_toml_and_env, cli::LiveBuilderConfig, config::Config}, - primitives::{MempoolTx, Order, TransactionSignedEcRecoveredWithBlobs}, - roothash::RootHashMode, - utils::{default_cfg_env, Signer}, + utils::{extract_onchain_block_txs, find_suggested_fee_recipient, http_provider}, }; -use reth::{ - payload::PayloadId, - providers::{BlockNumReader, BlockReader}, -}; -use reth_payload_builder::{database::CachedReads, EthPayloadBuilderAttributes}; +use reth::providers::BlockNumReader; +use reth_payload_builder::database::CachedReads; use reth_provider::StateProvider; -use revm_primitives::{BlobExcessGasAndPrice, BlockEnv, SpecId}; use std::{path::PathBuf, sync::Arc, time::Instant}; +use tracing::{debug, info}; #[derive(Parser, Debug)] struct Cli { #[clap(long, help = "bench iterations", default_value = "20")] iters: usize, - #[clap(help = "Config file path")] + #[clap( + long, + help = "external block provider", + env = "RPC_URL", + default_value = "http://127.0.0.1:8545" + )] + rpc_url: String, + #[clap(long, help = "Config file path", env = "RBUILDER_CONFIG")] config: PathBuf, } @@ -36,7 +38,9 @@ async fn main() -> eyre::Result<()> { let config: Config = load_config_toml_and_env(cli.config)?; config.base_config().setup_tracing_subsriber()?; - let chain = config.base_config().chain_spec()?; + let rpc = http_provider(cli.rpc_url.parse()?); + + let chain_spec = config.base_config().chain_spec()?; let factory = config .base_config() @@ -44,99 +48,96 @@ async fn main() -> eyre::Result<()> { .provider_factory_unchecked(); let last_block = factory.last_block_number()?; - let block_data = factory - .block_by_number(last_block)? - .ok_or_else(|| eyre::eyre!("Block not found"))?; - - let signer = Signer::try_from_secret(B256::random())?; - - let cfg_env = default_cfg_env(&chain, block_data.timestamp); - - let ctx = BlockBuildingContext { - block_env: BlockEnv { - number: U256::from(block_data.number), - coinbase: signer.address, - timestamp: U256::from(block_data.timestamp), - gas_limit: U256::from(block_data.gas_limit), - basefee: U256::from(block_data.base_fee_per_gas.unwrap_or_default()), - difficulty: Default::default(), - prevrandao: Some(block_data.difficulty.into()), - blob_excess_gas_and_price: block_data.excess_blob_gas.map(BlobExcessGasAndPrice::new), - }, - initialized_cfg: cfg_env, - attributes: EthPayloadBuilderAttributes { - id: PayloadId::new([0u8; 8]), - parent: block_data.parent_hash, - timestamp: block_data.timestamp, - suggested_fee_recipient: Default::default(), - prev_randao: Default::default(), - withdrawals: block_data.withdrawals.clone().unwrap_or_default(), - parent_beacon_block_root: block_data.parent_beacon_block_root, - }, - chain_spec: chain.clone(), - builder_signer: Some(signer), - extra_data: Vec::new(), - blocklist: Default::default(), - excess_blob_gas: block_data.excess_blob_gas, - spec_id: SpecId::LATEST, - }; - - // Get the landed orders (all Order::Tx) from the block - let orders = block_data - .body - .iter() - .map(|tx| { - let tx = tx - .try_ecrecovered() - .ok_or_else(|| eyre::eyre!("Failed to recover tx"))?; - let tx = TransactionSignedEcRecoveredWithBlobs::new_for_testing(tx); - let tx = MempoolTx::new(tx); - Ok::<_, eyre::Error>(Order::Tx(tx)) - }) - .collect::, _>>()?; - - let mut state_provider = - Arc::::from(factory.history_by_block_number(block_data.number - 1)?); - let (sim_orders, _) = simulate_all_orders_with_sim_tree(factory.clone(), &ctx, &orders, false)?; - tracing::info!( - "Block: {}, simulated orders: {}", - block_data.number, - sim_orders.len() + let onchain_block = rpc + .get_block_by_number((last_block + 1).into(), true) + .await? + .ok_or_else(|| eyre::eyre!("block not found on rpc"))?; + + let txs = extract_onchain_block_txs(&onchain_block)?; + let suggested_fee_recipient = find_suggested_fee_recipient(&onchain_block, &txs); + info!( + "Block number: {}, txs: {}", + onchain_block.header.number, + txs.len() + ); + + let coinbase = onchain_block.header.miner; + + let ctx = BlockBuildingContext::from_onchain_block( + onchain_block, + chain_spec, + None, + Default::default(), + coinbase, + suggested_fee_recipient, + None, ); - let mut build_times_mus = Vec::new(); - let mut finalize_time_mus = Vec::new(); + // let signer = Signer::try_from_secret(B256::random())?; + + let state_provider = + Arc::::from(factory.history_by_block_number(last_block)?); + + let mut build_times_ms = Vec::new(); + let mut finalize_time_ms = Vec::new(); let mut cached_reads = Some(CachedReads::default()); for _ in 0..cli.iters { - let mut partial_block = PartialBlock::new(true, None); - let mut block_state = - BlockState::new_arc(state_provider).with_cached_reads(cached_reads.unwrap_or_default()); - let build_time = Instant::now(); - partial_block.pre_block_call(&ctx, &mut block_state)?; - for order in &sim_orders { - let _ = partial_block.commit_order(order, &ctx, &mut block_state)?; - } - let build_time = build_time.elapsed(); - - let finalize_time = Instant::now(); - let finalized_block = partial_block.finalize( - &mut block_state, - &ctx, - factory.clone(), - RootHashMode::IgnoreParentHash, - config.base_config().root_hash_task_pool()?, - )?; - let finalize_time = finalize_time.elapsed(); - - cached_reads = Some(finalized_block.cached_reads); - - build_times_mus.push(build_time.as_micros()); - finalize_time_mus.push(finalize_time.as_micros()); - state_provider = block_state.into_provider(); + let ctx = ctx.clone(); + let txs = txs.clone(); + let state_provider = state_provider.clone(); + let factory = factory.clone(); + let config = config.clone(); + let root_hash_config = config.base_config.live_root_hash_config()?; + let (new_cached_reads, build_time, finalize_time) = + tokio::task::spawn_blocking(move || -> eyre::Result<_> { + let partial_block = PartialBlock::new(true, None); + let mut state = BlockState::new_arc(state_provider) + .with_cached_reads(cached_reads.unwrap_or_default()); + + let build_time = Instant::now(); + + let mut cumulative_gas_used = 0; + let mut cumulative_blob_gas_used = 0; + for (idx, tx) in txs.into_iter().enumerate() { + let result = { + let mut fork = PartialBlockFork::new(&mut state); + fork.commit_tx(&tx, &ctx, cumulative_gas_used, 0, cumulative_blob_gas_used)? + .with_context(|| { + format!("Failed to commit tx: {} {:?}", idx, tx.hash()) + })? + }; + cumulative_gas_used += result.gas_used; + cumulative_blob_gas_used += result.blob_gas_used; + } + + let build_time = build_time.elapsed(); + + let finalize_time = Instant::now(); + let finalized_block = partial_block.finalize( + &mut state, + &ctx, + factory.clone(), + root_hash_config.clone(), + config.base_config().root_hash_task_pool()?, + )?; + let finalize_time = finalize_time.elapsed(); + + debug!( + "Calculated root hash: {:?}", + finalized_block.sealed_block.state_root + ); + + Ok((finalized_block.cached_reads, build_time, finalize_time)) + }) + .await??; + + cached_reads = Some(new_cached_reads); + build_times_ms.push(build_time.as_millis()); + finalize_time_ms.push(finalize_time.as_millis()); } - report_time_data("build", &build_times_mus); - report_time_data("finalize", &finalize_time_mus); + report_time_data("build", &build_times_ms); + report_time_data("finalize", &finalize_time_ms); Ok(()) } diff --git a/crates/rbuilder/src/bin/dummy-builder.rs b/crates/rbuilder/src/bin/dummy-builder.rs index f8384946..561a9294 100644 --- a/crates/rbuilder/src/bin/dummy-builder.rs +++ b/crates/rbuilder/src/bin/dummy-builder.rs @@ -34,7 +34,7 @@ use rbuilder::{ mev_boost::{MevBoostRelay, RelayConfig}, SimulatedOrder, }, - roothash::RootHashMode, + roothash::RootHashConfig, utils::Signer, }; use reth::{providers::ProviderFactory, tasks::pool::BlockingTaskPool}; @@ -199,7 +199,7 @@ impl DummyBuildingAlgorithm { let mut block_building_helper = BlockBuildingHelperFromDB::new( provider_factory.clone(), self.root_hash_task_pool.clone(), - RootHashMode::CorrectRoot, + RootHashConfig::live_config(false, false), ctx.clone(), None, BUILDER_NAME.to_string(), diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index e15bfa03..dfe95d9a 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -21,7 +21,7 @@ use crate::{ Sorting, }, primitives::SimulatedOrder, - roothash::RootHashMode, + roothash::RootHashConfig, telemetry, }; @@ -95,7 +95,7 @@ pub struct BlockBuildingHelperFromDB { /// Needed to get the initial state and the final root hash calculation. provider_factory: ProviderFactory, root_hash_task_pool: BlockingTaskPool, - root_hash_mode: RootHashMode, + root_hash_config: RootHashConfig, /// Token to cancel in case of fatal error (if we believe that it's impossible to build for this block). cancel_on_fatal_error: CancellationToken, } @@ -134,7 +134,7 @@ impl BlockBuildingHelperFromDB { pub fn new( provider_factory: ProviderFactory, root_hash_task_pool: BlockingTaskPool, - root_hash_mode: RootHashMode, + root_hash_config: RootHashConfig, building_ctx: BlockBuildingContext, cached_reads: Option, builder_name: String, @@ -177,7 +177,7 @@ impl BlockBuildingHelperFromDB { built_block_trace: BuiltBlockTrace::new(), provider_factory, root_hash_task_pool, - root_hash_mode, + root_hash_config, cancel_on_fatal_error, }) } @@ -325,7 +325,7 @@ impl BlockBuildingHelper for BlockBuildingHelper &mut self.block_state, &self.building_ctx, self.provider_factory.clone(), - self.root_hash_mode, + self.root_hash_config, self.root_hash_task_pool, ) { Ok(finalized_block) => finalized_block, diff --git a/crates/rbuilder/src/building/builders/mod.rs b/crates/rbuilder/src/building/builders/mod.rs index c5826053..9d5b1cfb 100644 --- a/crates/rbuilder/src/building/builders/mod.rs +++ b/crates/rbuilder/src/building/builders/mod.rs @@ -7,6 +7,7 @@ use crate::{ building::{BlockBuildingContext, BlockOrders, BuiltBlockTrace, SimulatedOrderSink, Sorting}, live_builder::{payload_events::MevBoostSlotData, simulation::SimulatedOrderCommand}, primitives::{AccountNonce, OrderId, SimulatedOrder}, + roothash::RootHashConfig, utils::{is_provider_factory_health_error, NonceCache}, }; use ahash::HashSet; @@ -37,6 +38,7 @@ pub struct Block { #[derive(Debug)] pub struct LiveBuilderInput { pub provider_factory: ProviderFactory, + pub root_hash_config: RootHashConfig, pub root_hash_task_pool: BlockingTaskPool, pub ctx: BlockBuildingContext, pub input: broadcast::Receiver, diff --git a/crates/rbuilder/src/building/builders/ordering_builder.rs b/crates/rbuilder/src/building/builders/ordering_builder.rs index aac7f539..42790a05 100644 --- a/crates/rbuilder/src/building/builders/ordering_builder.rs +++ b/crates/rbuilder/src/building/builders/ordering_builder.rs @@ -21,7 +21,7 @@ use reth::providers::ProviderFactory; use reth_db::database::Database; use tokio_util::sync::CancellationToken; -use crate::{roothash::RootHashMode, utils::check_provider_factory_health}; +use crate::{roothash::RootHashConfig, utils::check_provider_factory_health}; use reth::tasks::pool::BlockingTaskPool; use reth_payload_builder::database::CachedReads; use serde::Deserialize; @@ -79,6 +79,7 @@ pub fn run_ordering_builder( input.builder_name, input.ctx, config.clone(), + input.root_hash_config, ); // this is a hack to mark used orders until built block trace is implemented as a sane thing @@ -147,8 +148,8 @@ pub fn backtest_simulate_block( input.builder_name, input.ctx.clone(), ordering_config, + RootHashConfig::skip_root_hash(), ) - .with_skip_root_hash() .with_cached_reads(input.cached_reads.unwrap_or_default()); let block_builder = builder.build_block( block_orders, @@ -175,7 +176,7 @@ pub struct OrderingBuilderContext { builder_name: String, ctx: BlockBuildingContext, config: OrderingBuilderConfig, - root_hash_mode: RootHashMode, + root_hash_config: RootHashConfig, // caches cached_reads: Option, @@ -192,6 +193,7 @@ impl OrderingBuilderContext { builder_name: String, ctx: BlockBuildingContext, config: OrderingBuilderConfig, + root_hash_config: RootHashConfig, ) -> Self { Self { provider_factory, @@ -199,21 +201,13 @@ impl OrderingBuilderContext { builder_name, ctx, config, - root_hash_mode: RootHashMode::CorrectRoot, + root_hash_config, cached_reads: None, failed_orders: HashSet::default(), order_attempts: HashMap::default(), } } - /// Should be used only in backtest - pub fn with_skip_root_hash(self) -> Self { - Self { - root_hash_mode: RootHashMode::SkipRootHash, - ..self - } - } - pub fn with_cached_reads(self, cached_reads: CachedReads) -> Self { Self { cached_reads: Some(cached_reads), @@ -253,7 +247,7 @@ impl OrderingBuilderContext { let mut block_building_helper = BlockBuildingHelperFromDB::new( self.provider_factory.clone(), self.root_hash_task_pool.clone(), - self.root_hash_mode, + self.root_hash_config.clone(), new_ctx, self.cached_reads.take(), self.builder_name.clone(), @@ -337,6 +331,7 @@ impl OrderingBuilderContext { #[derive(Debug)] pub struct OrderingBuildingAlgorithm { + root_hash_config: RootHashConfig, root_hash_task_pool: BlockingTaskPool, sbundle_mergeabe_signers: Vec
, config: OrderingBuilderConfig, @@ -345,12 +340,14 @@ pub struct OrderingBuildingAlgorithm { impl OrderingBuildingAlgorithm { pub fn new( + root_hash_config: RootHashConfig, root_hash_task_pool: BlockingTaskPool, sbundle_mergeabe_signers: Vec
, config: OrderingBuilderConfig, name: String, ) -> Self { Self { + root_hash_config, root_hash_task_pool, sbundle_mergeabe_signers, config, @@ -367,6 +364,7 @@ impl BlockBuildingAlgorithm for OrderingBuil fn build_blocks(&self, input: BlockBuildingAlgorithmInput) { let live_input = LiveBuilderInput { provider_factory: input.provider_factory, + root_hash_config: self.root_hash_config.clone(), root_hash_task_pool: self.root_hash_task_pool.clone(), ctx: input.ctx.clone(), input: input.input, diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index c785cef5..491e51f8 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -11,11 +11,12 @@ pub mod sim; pub mod testing; pub mod tracers; pub use block_orders::BlockOrders; +use eth_sparse_mpt::SparseTrieSharedCache; use reth_primitives::proofs::calculate_requests_root; use crate::{ primitives::{Order, OrderId, SimValue, SimulatedOrder, TransactionSignedEcRecoveredWithBlobs}, - roothash::calculate_state_root, + roothash::{calculate_state_root, RootHashConfig}, utils::{a2r_withdrawal, calc_gas_limit, timestamp_as_u64, Signer}, }; use ahash::HashSet; @@ -50,7 +51,7 @@ use thiserror::Error; use time::OffsetDateTime; use self::tracers::SimulationTracer; -use crate::{roothash::RootHashMode, utils::default_cfg_env}; +use crate::utils::default_cfg_env; pub use block_orders::*; pub use built_block_trace::*; #[cfg(test)] @@ -76,6 +77,7 @@ pub struct BlockBuildingContext { pub excess_blob_gas: Option, /// Version of the EVM that we are going to use pub spec_id: SpecId, + pub shared_sparse_mpt_cache: SparseTrieSharedCache, } impl BlockBuildingContext { @@ -141,6 +143,7 @@ impl BlockBuildingContext { extra_data, excess_blob_gas, spec_id, + shared_sparse_mpt_cache: Default::default(), } } @@ -225,6 +228,7 @@ impl BlockBuildingContext { extra_data: Vec::new(), excess_blob_gas: onchain_block.header.excess_blob_gas.map(|b| b as u64), spec_id, + shared_sparse_mpt_cache: Default::default(), } } @@ -555,7 +559,7 @@ impl PartialBlock { state: &mut BlockState, ctx: &BlockBuildingContext, provider_factory: ProviderFactory, - root_hash_mode: RootHashMode, + root_hash_config: RootHashConfig, root_hash_task_pool: BlockingTaskPool, ) -> eyre::Result { let (withdrawals_root, withdrawals) = { @@ -619,8 +623,9 @@ impl PartialBlock { provider_factory, ctx.attributes.parent, &execution_outcome, - root_hash_mode, root_hash_task_pool, + ctx.shared_sparse_mpt_cache.clone(), + root_hash_config, )?; // create the block header diff --git a/crates/rbuilder/src/live_builder/base_config.rs b/crates/rbuilder/src/live_builder/base_config.rs index cc2c0a8f..83764560 100644 --- a/crates/rbuilder/src/live_builder/base_config.rs +++ b/crates/rbuilder/src/live_builder/base_config.rs @@ -3,6 +3,7 @@ use crate::{ building::builders::UnfinishedBlockBuildingSinkFactory, live_builder::{order_input::OrderInputConfig, LiveBuilder}, + roothash::RootHashConfig, telemetry::{setup_reloadable_tracing_subscriber, LoggerConfig}, utils::{http_provider, BoxedProvider, ProviderFactoryReopener, Signer}, }; @@ -80,6 +81,10 @@ pub struct BaseConfig { /// Number of threads used for incoming order simulation pub simulation_threads: usize, + /// uses cached sparse trie for root hash + pub root_hash_use_sparse_trie: bool, + /// compares result of root hash using sparse trie and reference root hash + pub root_hash_compare_sparse_trie: bool, pub root_hash_task_pool_threads: usize, pub watchdog_timeout_sec: u64, @@ -255,6 +260,18 @@ impl BaseConfig { )) } + pub fn live_root_hash_config(&self) -> eyre::Result { + if self.root_hash_compare_sparse_trie && !self.root_hash_use_sparse_trie { + eyre::bail!( + "root_hash_compare_sparse_trie can't be set without root_hash_use_sparse_trie" + ); + } + Ok(RootHashConfig::live_config( + self.root_hash_use_sparse_trie, + self.root_hash_compare_sparse_trie, + )) + } + pub fn coinbase_signer(&self) -> eyre::Result { coinbase_signer_from_secret_key(&self.coinbase_secret_key.value()?) } @@ -407,6 +424,8 @@ impl Default for BaseConfig { blocklist_file_path: None, extra_data: "extra_data_change_me".to_string(), root_hash_task_pool_threads: 1, + root_hash_use_sparse_trie: false, + root_hash_compare_sparse_trie: false, watchdog_timeout_sec: 60 * 3, backtest_fetch_mempool_data_dir: "/mnt/data/mempool".into(), backtest_fetch_eth_rpc_url: "http://127.0.0.1:8545".to_string(), diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index 2cc364a0..bb52632b 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -28,6 +28,7 @@ use crate::{ }, mev_boost::BLSBlockSigner, primitives::mev_boost::{MevBoostRelay, RelayConfig}, + roothash::RootHashConfig, utils::{build_info::rbuilder_version, ProviderFactoryReopener, Signer}, validation_api_client::ValidationAPIClient, }; @@ -294,9 +295,11 @@ impl LiveBuilderConfig for Config { .base_config .create_builder(cancellation_token, sink_factory, payload_event) .await?; + let root_hash_config = self.base_config.live_root_hash_config()?; let root_hash_task_pool = self.base_config.root_hash_task_pool()?; let builders = create_builders( self.live_builders()?, + root_hash_config, root_hash_task_pool, self.base_config.sbundle_mergeabe_signers(), ); @@ -423,23 +426,33 @@ pub fn coinbase_signer_from_secret_key(secret_key: &str) -> eyre::Result fn create_builders( configs: Vec, + root_hash_config: RootHashConfig, root_hash_task_pool: BlockingTaskPool, sbundle_mergeabe_signers: Vec
, ) -> Vec>>> { configs .into_iter() - .map(|cfg| create_builder(cfg, &root_hash_task_pool, &sbundle_mergeabe_signers)) + .map(|cfg| { + create_builder( + cfg, + &root_hash_config, + &root_hash_task_pool, + &sbundle_mergeabe_signers, + ) + }) .collect() } fn create_builder( cfg: BuilderConfig, + root_hash_config: &RootHashConfig, root_hash_task_pool: &BlockingTaskPool, sbundle_mergeabe_signers: &[Address], ) -> Arc>> { match cfg.builder { SpecificBuilderConfig::OrderingBuilder(order_cfg) => { Arc::new(OrderingBuildingAlgorithm::new( + root_hash_config.clone(), root_hash_task_pool.clone(), sbundle_mergeabe_signers.to_vec(), order_cfg, diff --git a/crates/rbuilder/src/roothash/mod.rs b/crates/rbuilder/src/roothash/mod.rs index 35a77ba4..859b7ea0 100644 --- a/crates/rbuilder/src/roothash/mod.rs +++ b/crates/rbuilder/src/roothash/mod.rs @@ -1,10 +1,14 @@ use alloy_primitives::B256; +use eth_sparse_mpt::reth_sparse_trie::{ + calculate_root_hash_with_sparse_trie, SparseTrieError, SparseTrieSharedCache, +}; use reth::{ providers::{providers::ConsistentDbView, ExecutionOutcome, ProviderFactory}, tasks::pool::BlockingTaskPool, }; use reth_db::database::Database; use reth_trie_parallel::async_root::{AsyncStateRoot, AsyncStateRootError}; +use tracing::trace; #[derive(Debug, Clone, Copy)] pub enum RootHashMode { @@ -19,15 +23,51 @@ pub enum RootHashMode { SkipRootHash, } +#[derive(Debug, thiserror::Error)] +pub enum RootHashError { + #[error("Async state root: {0:?}")] + AsyncStateRoot(#[from] AsyncStateRootError), + #[error("Sparse state root: {0:?}")] + SparseStateRoot(#[from] SparseTrieError), + #[error("State root verification error")] + Verification, +} + +#[derive(Debug, Clone)] +pub struct RootHashConfig { + pub mode: RootHashMode, + pub use_sparse_trie: bool, + pub compare_sparse_trie_output: bool, +} + +impl RootHashConfig { + pub fn skip_root_hash() -> Self { + Self { + mode: RootHashMode::SkipRootHash, + use_sparse_trie: false, + compare_sparse_trie_output: false, + } + } + + pub fn live_config(use_sparse_trie: bool, compare_sparse_trie_output: bool) -> Self { + Self { + mode: RootHashMode::CorrectRoot, + use_sparse_trie, + compare_sparse_trie_output, + } + } +} + #[allow(clippy::too_many_arguments)] pub fn calculate_state_root( provider_factory: ProviderFactory, parent_hash: B256, outcome: &ExecutionOutcome, - mode: RootHashMode, blocking_task_pool: BlockingTaskPool, -) -> Result { - let consistent_db_view = match mode { + sparse_trie_shared_cache: SparseTrieSharedCache, + config: RootHashConfig, +) -> Result { + let consistent_db_view = match config.mode { RootHashMode::CorrectRoot => ConsistentDbView::new(provider_factory, Some(parent_hash)), RootHashMode::IgnoreParentHash => ConsistentDbView::new_with_latest_tip(provider_factory) .map_err(AsyncStateRootError::Provider)?, @@ -36,11 +76,40 @@ pub fn calculate_state_root( } }; - let hashed_post_state = outcome.hash_state_slow(); + let reference_root_hash = if config.compare_sparse_trie_output { + let hashed_post_state = outcome.hash_state_slow(); + + let async_root_calculator = AsyncStateRoot::new( + consistent_db_view.clone(), + blocking_task_pool.clone(), + hashed_post_state.clone(), + ); + + futures::executor::block_on(async_root_calculator.incremental_root())? + } else { + B256::ZERO + }; + + let root = if config.use_sparse_trie { + let (root, metrics) = calculate_root_hash_with_sparse_trie( + consistent_db_view, + outcome, + sparse_trie_shared_cache, + ); + trace!(?metrics, "Sparse trie metrics"); + root? + } else { + let hashed_post_state = outcome.hash_state_slow(); + + let async_root_calculator = + AsyncStateRoot::new(consistent_db_view, blocking_task_pool, hashed_post_state); + + futures::executor::block_on(async_root_calculator.incremental_root())? + }; - let async_root_calculator = - AsyncStateRoot::new(consistent_db_view, blocking_task_pool, hashed_post_state); - let root = futures::executor::block_on(async_root_calculator.incremental_root())?; + if config.compare_sparse_trie_output && reference_root_hash != root { + return Err(RootHashError::Verification); + } Ok(root) } diff --git a/crates/rbuilder/src/utils/mod.rs b/crates/rbuilder/src/utils/mod.rs index 8483dffb..7410ed8d 100644 --- a/crates/rbuilder/src/utils/mod.rs +++ b/crates/rbuilder/src/utils/mod.rs @@ -14,19 +14,22 @@ pub mod test_utils; pub mod tracing; use alloy_network::Ethereum; -use alloy_primitives::{Sign, I256, U256}; +use alloy_primitives::{Address, Sign, I256, U256}; use alloy_provider::RootProvider; use alloy_transport::BoxTransport; -use reth_chainspec::ChainSpec; -use reth_evm_ethereum::revm_spec_by_timestamp_after_merge; -use revm_primitives::{CfgEnv, CfgEnvWithHandlerCfg}; -use std::cmp::{max, min}; - +use crate::primitives::serialize::{RawTx, TxEncoding}; +use crate::primitives::TransactionSignedEcRecoveredWithBlobs; +use alloy_consensus::TxEnvelope; +use alloy_eips::eip2718::Encodable2718; pub use noncer::{NonceCache, NonceCacheRef}; pub use provider_factory_reopen::{ check_provider_factory_health, is_provider_factory_health_error, ProviderFactoryReopener, }; +use reth_chainspec::ChainSpec; +use reth_evm_ethereum::revm_spec_by_timestamp_after_merge; +use revm_primitives::{CfgEnv, CfgEnvWithHandlerCfg}; +use std::cmp::{max, min}; pub use test_data_generator::TestDataGenerator; use time::OffsetDateTime; pub use tx_signer::Signer; @@ -201,6 +204,40 @@ pub fn signed_uint_delta(a: U256, b: U256) -> I256 { a.checked_sub(b).expect("Subtraction overflow") } +pub fn find_suggested_fee_recipient( + block: &alloy_rpc_types::Block, + txs: &[TransactionSignedEcRecoveredWithBlobs], +) -> Address { + let coinbase = block.header.miner; + let (last_tx_signer, last_tx_to) = if let Some((signer, to)) = txs + .last() + .map(|tx| (tx.signer(), tx.to().unwrap_or_default())) + { + (signer, to) + } else { + return coinbase; + }; + + if last_tx_signer == coinbase { + last_tx_to + } else { + coinbase + } +} + +pub fn extract_onchain_block_txs( + onchain_block: &alloy_rpc_types::Block, +) -> eyre::Result> { + let mut result = Vec::new(); + for tx in onchain_block.transactions.clone().into_transactions() { + let tx_envelope: TxEnvelope = tx.try_into()?; + let encoded = tx_envelope.encoded_2718(); + let tx = RawTx { tx: encoded.into() }.decode(TxEncoding::NoBlobData)?; + result.push(tx.tx_with_blobs); + } + Ok(result) +} + #[cfg(test)] mod test { use super::*; From ab0529f9ea7fd77456183edec25a97778aeec3ef Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:49:47 -0300 Subject: [PATCH 17/30] New improved bidding core. (#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This new bidding core is designed to encapsulate the essence of the bidding process. The `SlotBidder` now focuses solely on mathematical calculations and bidding activities, operating without any inherent subsystems since all necessary information is provided externally. The `SlotBidder` simply listens for new blocks and incoming bids from competitors. ```rust pub trait SlotBidder: UnfinishedBlockBuildingSink + BidValueObs {} ``` The `BiddingService` has been enhanced to gather information on landed blocks, enabling it to fine-tune bidding strategies and subsidies. Additionally, it can be instructed to pursue a block with heightened intensity: ```rust pub trait BiddingService: std::fmt::Debug + Send + Sync { fn create_slot_bidder( &mut self, block: u64, slot: u64, slot_end_timestamp: u64, bid_maker: Box, ) -> Arc; /// When invoked, this method instructs all current or future `SlotBidder` instances working on the specified block to bid more aggressively in order to secure it. fn must_win_block(&self, block: u64); /// This method notifies the service of blocks that we have successfully landed. fn update_new_landed_blocks_detected( &self, landed_block_interval_info: LandedBlockIntervalInfo, ); /// We inform the `BiddingService` of any issues encountered while reading landed blocks, which may prompt a strategy adjustment (e.g., pausing bidding until the next update). fn update_failed_reading_new_landed_blocks(&self); } ``` The `bid_maker` is provided to the created `SlotBidder`, enabling it to bid autonomously whenever it sees fit. ## 💡 Motivation and Context This new core is the first step to allow having secret sandboxed code in a TEE environment. ## ✅ I have completed the following steps: * [X] Run `make lint` * [X] Run `make test` * [ ] Added tests (if applicable) --- .../builders/block_building_helper.rs | 2 +- .../live_builder/block_output/bid_observer.rs | 2 +- .../bid_value_source/best_bid_sync_source.rs | 49 +++++ .../bid_value_source/interfaces.rs | 15 ++ .../block_output/bid_value_source/mod.rs | 4 + .../bid_value_source/null_bid_value_source.rs | 12 ++ .../block_output/bidding/interfaces.rs | 101 ++++++++++ .../live_builder/block_output/bidding/mod.rs | 61 +----- .../bidding/sequential_sealer_bid_maker.rs | 112 +++++++++++ .../bidding/true_block_value_bidder.rs | 85 +++++++++ .../bidding/wallet_balance_watcher.rs | 175 ++++++++++++++++++ .../block_output/block_finisher.rs | 67 ------- .../block_output/block_finisher_factory.rs | 55 ------ .../block_sealing_bidder_factory.rs | 163 ++++++++++++++++ .../src/live_builder/block_output/mod.rs | 4 +- .../live_builder/block_output/relay_submit.rs | 38 ++-- crates/rbuilder/src/live_builder/config.rs | 42 ++++- 17 files changed, 772 insertions(+), 215 deletions(-) create mode 100644 crates/rbuilder/src/live_builder/block_output/bid_value_source/best_bid_sync_source.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bid_value_source/mod.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bid_value_source/null_bid_value_source.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bidding/true_block_value_bidder.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/bidding/wallet_balance_watcher.rs delete mode 100644 crates/rbuilder/src/live_builder/block_output/block_finisher.rs delete mode 100644 crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs create mode 100644 crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index dfe95d9a..18559e97 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -34,7 +34,7 @@ use super::Block; /// 2 - Call lots of commit_order. /// 3 - Call set_trace_fill_time when you are done calling commit_order (we still have to review this step). /// 4 - Call finalize_block. -pub trait BlockBuildingHelper: Send { +pub trait BlockBuildingHelper: Send + Sync { fn box_clone(&self) -> Box; /// Tries to add an order to the end of the block. diff --git a/crates/rbuilder/src/live_builder/block_output/bid_observer.rs b/crates/rbuilder/src/live_builder/block_output/bid_observer.rs index 4049c546..5e8f0a13 100644 --- a/crates/rbuilder/src/live_builder/block_output/bid_observer.rs +++ b/crates/rbuilder/src/live_builder/block_output/bid_observer.rs @@ -3,7 +3,7 @@ use reth_primitives::SealedBlock; use crate::{building::BuiltBlockTrace, mev_boost::SubmitBlockRequest}; -/// Trait that receives every bid made to the relays. +/// Trait that receives every bid made by us to the relays. pub trait BidObserver: std::fmt::Debug { /// This callback is executed after the bid was made so it gives away ownership of the data. /// This should NOT block since it's executed in the submitting thread. diff --git a/crates/rbuilder/src/live_builder/block_output/bid_value_source/best_bid_sync_source.rs b/crates/rbuilder/src/live_builder/block_output/bid_value_source/best_bid_sync_source.rs new file mode 100644 index 00000000..c91ee984 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bid_value_source/best_bid_sync_source.rs @@ -0,0 +1,49 @@ +use super::interfaces::{BidValueObs, BidValueSource}; +use alloy_primitives::U256; +use std::sync::{Arc, Mutex}; + +/// Simple struct tracking the last best bid and asking it in a sync way via best_bid_value. +pub struct BestBidSyncSource { + best_bid_source_inner: Arc, + bid_value_source: Arc, +} + +impl Drop for BestBidSyncSource { + fn drop(&mut self) { + self.bid_value_source + .unsubscribe(self.best_bid_source_inner.clone()); + } +} + +impl BestBidSyncSource { + pub fn new( + bid_value_source: Arc, + block_number: u64, + slot_number: u64, + ) -> Self { + let best_bid_source_inner = Arc::new(BestBidSyncSourceInner::default()); + bid_value_source.subscribe(block_number, slot_number, best_bid_source_inner.clone()); + Self { + best_bid_source_inner, + bid_value_source, + } + } + + pub fn best_bid_value(&self) -> Option { + *self.best_bid_source_inner.best_bid.lock().unwrap() + } +} + +#[derive(Debug, Default)] +struct BestBidSyncSourceInner { + best_bid: Mutex>, +} + +impl BidValueObs for BestBidSyncSourceInner { + fn update_new_bid(&self, bid: U256) { + let mut best_bid = self.best_bid.lock().unwrap(); + if best_bid.map_or(true, |old_bid| old_bid < bid) { + *best_bid = Some(bid); + } + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs b/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs new file mode 100644 index 00000000..a936770b --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs @@ -0,0 +1,15 @@ +use alloy_primitives::U256; +use std::sync::Arc; + +/// Sync + Send to allow to be called from another thread. +pub trait BidValueObs: std::fmt::Debug + Sync + Send { + /// @Pending: add source of the bid. + fn update_new_bid(&self, bid: U256); +} + +/// Object watching a stream af the bids made. +/// Allows us to subscribe to notifications for particular blocks/slots. +pub trait BidValueSource: std::fmt::Debug { + fn subscribe(&self, block_number: u64, slot_number: u64, obs: Arc); + fn unsubscribe(&self, obs: Arc); +} diff --git a/crates/rbuilder/src/live_builder/block_output/bid_value_source/mod.rs b/crates/rbuilder/src/live_builder/block_output/bid_value_source/mod.rs new file mode 100644 index 00000000..a7514c08 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bid_value_source/mod.rs @@ -0,0 +1,4 @@ +//! This module handles all objects needed to get feedback from the bids made by the competition. +pub mod best_bid_sync_source; +pub mod interfaces; +pub mod null_bid_value_source; diff --git a/crates/rbuilder/src/live_builder/block_output/bid_value_source/null_bid_value_source.rs b/crates/rbuilder/src/live_builder/block_output/bid_value_source/null_bid_value_source.rs new file mode 100644 index 00000000..ea1c40de --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bid_value_source/null_bid_value_source.rs @@ -0,0 +1,12 @@ +use std::sync::Arc; + +use super::interfaces::{BidValueObs, BidValueSource}; + +/// BidValueSource that will NOT report anything. +#[derive(Debug)] +pub struct NullBidValueSource {} + +impl BidValueSource for NullBidValueSource { + fn subscribe(&self, _block_number: u64, _slot_number: u64, _obs: Arc) {} + fn unsubscribe(&self, _obs: Arc) {} +} diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs b/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs new file mode 100644 index 00000000..35b61b97 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs @@ -0,0 +1,101 @@ +use std::sync::Arc; + +use crate::{ + building::builders::{block_building_helper::BlockBuildingHelper, UnfinishedBlockBuildingSink}, + live_builder::block_output::bid_value_source::interfaces::BidValueObs, +}; +use alloy_primitives::U256; +use reth_primitives::BlockNumber; +use time::OffsetDateTime; +use tokio_util::sync::CancellationToken; + +/// Trait in charge of bidding blocks. +/// It is created for each block / slot. +/// Via UnfinishedBlockBuildingSink it gets the new biddable blocks. +/// Via BidValueObs it gets the competition bids that it should improve when possible. +/// On creation the concrete SlotBidder will get a BidMaker to make the bids. +pub trait SlotBidder: UnfinishedBlockBuildingSink + BidValueObs {} + +/// Bid we want to make. +pub struct Bid { + /// Block we should seal with payout tx of payout_tx_value. + block: Box, + /// payout_tx_value should be Some <=> block.can_add_payout_tx() + payout_tx_value: Option, +} + +impl std::fmt::Debug for Bid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Bid") + .field("payout_tx_value", &self.payout_tx_value) + .finish_non_exhaustive() + } +} + +impl Bid { + /// Creates a new Bid instance. + pub fn new(block: Box, payout_tx_value: Option) -> Self { + Self { + block, + payout_tx_value, + } + } + + pub fn block(self) -> Box { + self.block + } + + /// Returns the payout transaction value. + pub fn payout_tx_value(&self) -> Option { + self.payout_tx_value + } +} + +/// Makes the actual bid (send it to the relay) +pub trait BidMaker: std::fmt::Debug { + fn send_bid(&self, bid: Bid); +} + +/// Info about a onchain block from reth. +pub struct LandedBlockInfo { + pub block_number: BlockNumber, + pub block_timestamp: OffsetDateTime, + pub builder_balance: U256, + /// true -> we landed this block. + /// If false we could have landed it in coinbase == fee recipient mode but balance wouldn't change so we don't care. + pub beneficiary_is_builder: bool, +} + +/// Trait in charge of bidding. +/// We use one for the whole execution and ask for a [SlotBidder] for each particular slot. +/// After BiddingService creation the builder will try to feed it all the needed update_new_landed_block_detected from the DB history. +/// To avoid exposing how much info the BiddingService uses we don't ask it anything and feed it the max history we are willing to read. +/// After that the builder will update each block via update_new_landed_block_detected. +pub trait BiddingService: std::fmt::Debug + Send + Sync { + fn create_slot_bidder( + &mut self, + block: u64, + slot: u64, + slot_timestamp: OffsetDateTime, + bid_maker: Box, + cancel: CancellationToken, + ) -> Arc; + + /// Access to BiddingServiceWinControl::must_win_block. + fn win_control(&self) -> Arc; + + /// We are notified about some landed blocks. + /// They are sorted in ascending order. + /// Consecutive calls will have consecutive block numbers. + fn update_new_landed_blocks_detected(&mut self, landed_blocks: &[LandedBlockInfo]); + + /// We let the BiddingService know we had some problem reading landed blocks just in case we wants to change his strategy (eg: stop bidding until next update_new_landed_blocks_detected) + fn update_failed_reading_new_landed_blocks(&mut self); +} + +/// Trait to control the must_win_block feature of the BiddingService. +/// It allows to use BiddingService as a Box (single threaded mutable access) but be able to call must_win_block from another thread. +pub trait BiddingServiceWinControl: Send + Sync + std::fmt::Debug { + /// If called, any current or future SlotBidder working on that block will bid more aggressively to win the block. + fn must_win_block(&self, block: u64); +} diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs b/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs index 404f4780..65ae2418 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs @@ -1,57 +1,4 @@ -use std::sync::Arc; - -use alloy_primitives::U256; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum SealInstruction { - /// Don't waste cycles sealing block that has no chances - Skip, - /// Set this value in the last tx before sealing block - Value(U256), -} - -/// Slot bidder is used by builder to decide what value should be put into the last tx. -/// It is created for each block / slot. -pub trait SlotBidder: Send + Sync + std::fmt::Debug { - /// Returns true if payment for the slot can go directly to fee recipient through coinbase. - fn is_pay_to_coinbase_allowed(&self) -> bool; - - /// Returns what value needs to be sent to the fee recipient or if block should be skipped. - fn seal_instruction( - &self, - unsealed_block_profit: U256, - slot_timestamp: time::OffsetDateTime, - ) -> SealInstruction; -} - -impl SlotBidder for () { - fn is_pay_to_coinbase_allowed(&self) -> bool { - true - } - - fn seal_instruction( - &self, - unsealed_block_profit: U256, - _slot_timestamp: time::OffsetDateTime, - ) -> SealInstruction { - SealInstruction::Value(unsealed_block_profit) - } -} - -pub trait BiddingService: std::fmt::Debug + Send + Sync { - fn create_slot_bidder( - &mut self, - block: u64, - slot: u64, - slot_end_timestamp: u64, - ) -> Arc; -} - -/// Creates () which implements the dummy SlotBidder which bids all true value -#[derive(Debug)] -pub struct DummyBiddingService {} -impl BiddingService for DummyBiddingService { - fn create_slot_bidder(&mut self, _: u64, _: u64, _: u64) -> Arc { - Arc::new(()) - } -} +pub mod interfaces; +pub mod sequential_sealer_bid_maker; +pub mod true_block_value_bidder; +pub mod wallet_balance_watcher; diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs b/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs new file mode 100644 index 00000000..8018aa86 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs @@ -0,0 +1,112 @@ +use std::sync::{Arc, Mutex}; +use tokio::sync::Notify; +use tokio_util::sync::CancellationToken; +use tracing::error; + +use crate::live_builder::block_output::relay_submit::BlockBuildingSink; + +use super::interfaces::{Bid, BidMaker}; + +/// BidMaker with a background task sealing only one bid at a time. +/// If several bids arrive while sealing another one we keep only the last one since we assume new is better. +#[derive(Debug)] +pub struct SequentialSealerBidMaker { + pending_bid: Arc, +} + +impl BidMaker for SequentialSealerBidMaker { + fn send_bid(&self, bid: Bid) { + self.pending_bid.update(bid); + } +} + +/// Object used to send new bids to the [SequentialSealerBidMakerProcess]. +#[derive(Debug)] +struct PendingBid { + /// Next bid to send. + bid: Mutex>, + /// Signaled when we set a new bid. + bid_notify: Notify, +} + +impl PendingBid { + fn new() -> Self { + Self { + bid: Default::default(), + bid_notify: Notify::new(), + } + } + pub async fn wait_for_change(&self) { + self.bid_notify.notified().await + } + /// Updates bid, replacing on current (we assume they are always increasing but we don't check it). + fn update(&self, bid: Bid) { + let mut current_bid = self.bid.lock().unwrap(); + *current_bid = Some(bid); + self.bid_notify.notify_one(); + } + + fn consume_bid(&self) -> Option { + let mut current_bid = self.bid.lock().unwrap(); + current_bid.take() + } +} + +impl SequentialSealerBidMaker { + pub fn new(sink: Arc, cancel: CancellationToken) -> Self { + let pending_bid = Arc::new(PendingBid::new()); + let mut sealing_process = SequentialSealerBidMakerProcess { + sink, + cancel, + pending_bid: pending_bid.clone(), + }; + + tokio::task::spawn(async move { + sealing_process.run().await; + }); + Self { pending_bid } + } +} + +/// Background task waiting for new bids to seal. +struct SequentialSealerBidMakerProcess { + /// Destination of the finished blocks. + sink: Arc, + cancel: CancellationToken, + pending_bid: Arc, +} + +impl SequentialSealerBidMakerProcess { + async fn run(&mut self) { + loop { + tokio::select! { + _ = self.pending_bid.wait_for_change() => self.check_for_new_bid().await, + _ = self.cancel.cancelled() => return + } + } + } + + /// block.finalize_block + self.sink.new_block inside spawn_blocking. + async fn check_for_new_bid(&mut self) { + if let Some(bid) = self.pending_bid.consume_bid() { + let payout_tx_val = bid.payout_tx_value(); + let block = bid.block(); + let block_number = block.building_context().block(); + match tokio::task::spawn_blocking(move || block.finalize_block(payout_tx_val)).await { + Ok(finalize_res) => match finalize_res { + Ok(res) => self.sink.new_block(res.block), + Err(error) => error!( + block_number, + ?error, + "Error on finalize_block on SequentialSealerBidMaker" + ), + }, + Err(error) => error!( + block_number, + ?error, + "Error on join finalize_block on on SequentialSealerBidMaker" + ), + } + } + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/true_block_value_bidder.rs b/crates/rbuilder/src/live_builder/block_output/bidding/true_block_value_bidder.rs new file mode 100644 index 00000000..4ff59fc1 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bidding/true_block_value_bidder.rs @@ -0,0 +1,85 @@ +use super::interfaces::{ + Bid, BidMaker, BiddingService, BiddingServiceWinControl, LandedBlockInfo, SlotBidder, +}; +use crate::{ + building::builders::{block_building_helper::BlockBuildingHelper, UnfinishedBlockBuildingSink}, + live_builder::block_output::bid_value_source::interfaces::BidValueObs, +}; +use alloy_primitives::U256; +use std::sync::Arc; +use time::OffsetDateTime; +use tokio_util::sync::CancellationToken; + +/// Bidding service giving a TrueBlockValueBidder +#[derive(Debug)] +pub struct TrueBlockValueBiddingService {} + +impl TrueBlockValueBiddingService { + /// _landed_blocks is passed to look like a real BiddingService... + pub fn new(_landed_blocks: &[LandedBlockInfo]) -> Self { + Self {} + } +} + +impl BiddingService for TrueBlockValueBiddingService { + fn create_slot_bidder( + &mut self, + _block: u64, + _slot: u64, + _slot_timestamp: OffsetDateTime, + bid_maker: Box, + _cancel: CancellationToken, + ) -> Arc { + Arc::new(TrueBlockValueBidder { bid_maker }) + } + + /// Dummy win control. + fn win_control(&self) -> Arc { + Arc::new(TrueBlockValueBiddingServiceWinControl {}) + } + + fn update_new_landed_blocks_detected(&mut self, _landed_blocks: &[LandedBlockInfo]) { + // No special behavior for landed blocks in this simple implementation. + } + + fn update_failed_reading_new_landed_blocks(&mut self) { + // No special behavior for landed blocks in this simple implementation. + } +} + +/// Bidder that bids every block using its true block value ignoring competition bids. +#[derive(Debug)] +struct TrueBlockValueBidder { + bid_maker: Box, +} + +impl SlotBidder for TrueBlockValueBidder {} + +impl UnfinishedBlockBuildingSink for TrueBlockValueBidder { + fn new_block(&self, block: Box) { + let payout_tx_value = if block.can_add_payout_tx() { + match block.true_block_value() { + Ok(tbv) => Some(tbv), + Err(_) => return, + } + } else { + None + }; + self.bid_maker.send_bid(Bid::new(block, payout_tx_value)); + } + + fn can_use_suggested_fee_recipient_as_coinbase(&self) -> bool { + true + } +} + +impl BidValueObs for TrueBlockValueBidder { + fn update_new_bid(&self, _bid: U256) {} +} + +#[derive(Debug)] +struct TrueBlockValueBiddingServiceWinControl {} + +impl BiddingServiceWinControl for TrueBlockValueBiddingServiceWinControl { + fn must_win_block(&self, _block: u64) {} +} diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/wallet_balance_watcher.rs b/crates/rbuilder/src/live_builder/block_output/bidding/wallet_balance_watcher.rs new file mode 100644 index 00000000..f22d1b34 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bidding/wallet_balance_watcher.rs @@ -0,0 +1,175 @@ +use std::{sync::Arc, time::Duration}; + +use alloy_primitives::{Address, BlockNumber, U256}; +use reth::{ + primitives::format_ether, + providers::{BlockNumReader, HeaderProvider, ProviderError, ProviderFactory}, +}; +use reth_db::DatabaseEnv; +use time::{error, OffsetDateTime}; +use tracing::{error, info}; + +use crate::telemetry::{add_subsidy_value, inc_subsidized_blocks}; + +use super::interfaces::LandedBlockInfo; + +/// Allows to monitor the evolution of our wallet for the landed blocks. +/// It's useful for bidders to detect profit and subsidies. +/// Ugly patch: it also updates metrics. +/// Usage: +/// 1 - Create one and you'll get also the latest history of balance changes. +/// 2 - After each new landed block is detected (or whenever you want) call update_to_block to get info up to that block. +#[derive(Debug)] +pub struct WalletBalanceWatcher { + provider_factory: ProviderFactory>, + builder_addr: Address, + /// Last block analyzed. balance is updated up to block_number (included). + block_number: BlockNumber, + balance: U256, +} + +#[derive(thiserror::Error, Debug)] +pub enum WalletError { + #[error("ProviderError: {0}")] + ProviderError(#[from] ProviderError), + #[error("HeaderNotFound for block {0}")] + HeaderNotFound(BlockNumber), + #[error("Invalid timestamp {0}")] + InvalidTimestamp(#[from] error::ComponentRange), + #[error("Unable to get initial balance")] + InitialBalance, +} + +struct BlockInfo { + timestamp: OffsetDateTime, + builder_balance: U256, + beneficiary: Address, + block_number: BlockNumber, +} + +impl BlockInfo { + fn as_landed_block_info(&self, buider_address: &Address) -> LandedBlockInfo { + LandedBlockInfo { + block_number: self.block_number, + block_timestamp: self.timestamp, + builder_balance: self.builder_balance, + beneficiary_is_builder: self.beneficiary == *buider_address, + } + } +} + +impl WalletBalanceWatcher { + /// Creates a WalletBalanceWatcher pre-analyzing a window of init_window_size size. + pub fn new( + provider_factory: ProviderFactory>, + builder_addr: Address, + init_window_size: Duration, + ) -> Result<(Self, Vec), WalletError> { + Self { + provider_factory, + builder_addr, + block_number: 0, + balance: U256::ZERO, + } + .init(init_window_size) + } + + /// Analyzes the past up to subsidy_window_size adding the subsidies. + /// Returns at least 1 LandedBlockInfo. + fn init( + mut self, + init_window_size: Duration, + ) -> Result<(Self, Vec), WalletError> { + let analysis_window_limit = OffsetDateTime::now_utc() - init_window_size; + self.block_number = self.provider_factory.last_block_number()?; + let mut block_number = self.block_number; + let last_block_info = self + .get_block_info(block_number) + .map_err(|_| WalletError::InitialBalance)?; + self.balance = last_block_info.builder_balance; + + // Store old balances as balance,ts decreasing ts order + let mut history = Vec::new(); + while let Ok(block_info) = self.get_block_info(block_number) { + if block_info.timestamp < analysis_window_limit && !history.is_empty() { + break; + } + history.push(block_info); + if block_number == 0 { + break; + } + block_number -= 1; + } + let landed_block_info_interval = history + .iter() + .rev() + .map(|block_info| block_info.as_landed_block_info(&self.builder_addr)) + .collect(); + Ok((self, landed_block_info_interval)) + } + + /// returns the wallet balance for the block and the block's timestamp + fn get_block_info(&mut self, block: BlockNumber) -> Result { + let builder_balance = self + .provider_factory + .history_by_block_number(block)? + .account_balance(self.builder_addr)? + .unwrap_or_default(); + let header = self + .provider_factory + .header_by_number(block)? + .ok_or(WalletError::HeaderNotFound(block))?; + Ok(BlockInfo { + timestamp: OffsetDateTime::from_unix_timestamp(header.timestamp as i64)?, + builder_balance, + block_number: block, + beneficiary: header.beneficiary, + }) + } + + /// If a subsidy is detected on the new block it answers its value. + /// We consider a subsidy as a decrease on balance on a block landed by the builder + fn get_subsidy(&self, prev_balance: &U256, block_info: &LandedBlockInfo) -> Option { + if block_info.builder_balance < *prev_balance && block_info.beneficiary_is_builder { + Some(prev_balance - block_info.builder_balance) + } else { + None + } + } + + /// Queries all the new blocks (from last successful update_to_block call or creation). + pub fn update_to_block( + &mut self, + new_block: BlockNumber, + ) -> Result, WalletError> { + if new_block <= self.block_number { + if new_block < self.block_number { + error!( + new_block, + self.block_number, "Tried to update WalletBalanceWatcher to the past" + ); + } + return Ok(Vec::new()); + } + let mut res = Vec::new(); + for block_number in self.block_number + 1..=new_block { + let block_info = self.get_block_info(block_number)?; + res.push(block_info.as_landed_block_info(&self.builder_addr)); + } + for landed_block_info in &res { + // Patch to add subsidy metrics. + if let Some(subsidy_value) = self.get_subsidy(&self.balance, landed_block_info) { + info!( + block_number = landed_block_info.block_number, + subsidy_value = format_ether(subsidy_value), + "Subsidy detected" + ); + add_subsidy_value(subsidy_value, true); + inc_subsidized_blocks(true); + } + self.balance = landed_block_info.builder_balance; + self.block_number = landed_block_info.block_number; + } + Ok(res) + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/block_finisher.rs b/crates/rbuilder/src/live_builder/block_output/block_finisher.rs deleted file mode 100644 index a5976b1b..00000000 --- a/crates/rbuilder/src/live_builder/block_output/block_finisher.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::sync::Arc; - -use tracing::{trace, warn}; - -use crate::building::builders::{ - block_building_helper::{BlockBuildingHelper, BlockBuildingHelperError}, - UnfinishedBlockBuildingSink, -}; - -use super::{ - bidding::{SealInstruction, SlotBidder}, - relay_submit::BlockBuildingSink, -}; - -/// UnfinishedBlockBuildingSink that ask the bidder how much to bid (or skip the block), finishes the blocks and sends them to a BlockBuildingSink. -#[derive(Debug)] -pub struct BlockFinisher { - /// Bidder we ask how to finish the blocks. - bidder: Arc, - /// Destination of the finished blocks. - sink: Arc, -} - -impl BlockFinisher { - pub fn new(bidder: Arc, sink: Arc) -> Self { - Self { bidder, sink } - } - - fn finish_and_submit( - &self, - block: Box, - ) -> Result<(), BlockBuildingHelperError> { - let payout_tx_value = if block.can_add_payout_tx() { - let available_value = block.true_block_value()?; - match self - .bidder - .seal_instruction(available_value, block.building_context().timestamp()) - { - SealInstruction::Value(value) => Some(value), - SealInstruction::Skip => { - trace!( - block = block.building_context().block(), - "Skipped block finalization", - ); - return Ok(()); - } - } - } else { - None - }; - self.sink - .new_block(block.finalize_block(payout_tx_value)?.block); - Ok(()) - } -} - -impl UnfinishedBlockBuildingSink for BlockFinisher { - fn new_block(&self, block: Box) { - if let Err(err) = self.finish_and_submit(block) { - warn!(?err, "Error finishing block"); - } - } - - fn can_use_suggested_fee_recipient_as_coinbase(&self) -> bool { - self.bidder.is_pay_to_coinbase_allowed() - } -} diff --git a/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs b/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs deleted file mode 100644 index 2f5daf92..00000000 --- a/crates/rbuilder/src/live_builder/block_output/block_finisher_factory.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::sync::Arc; - -use tokio_util::sync::CancellationToken; - -use crate::{ - building::builders::{UnfinishedBlockBuildingSink, UnfinishedBlockBuildingSinkFactory}, - live_builder::payload_events::MevBoostSlotData, -}; - -use super::{ - bidding::{BiddingService, SlotBidder}, - block_finisher::BlockFinisher, - relay_submit::{BuilderSinkFactory, NullBestBidSource}, -}; - -#[derive(Debug)] -pub struct BlockFinisherFactory { - bidding_service: Box, - /// Factory for the final destination for blocks. - block_sink_factory: Box, -} - -impl BlockFinisherFactory { - pub fn new( - bidding_service: Box, - block_sink_factory: Box, - ) -> Self { - Self { - bidding_service, - block_sink_factory, - } - } -} - -impl UnfinishedBlockBuildingSinkFactory for BlockFinisherFactory { - fn create_sink( - &mut self, - slot_data: MevBoostSlotData, - cancel: CancellationToken, - ) -> Arc { - let slot_bidder: Arc = self.bidding_service.create_slot_bidder( - slot_data.block(), - slot_data.slot(), - slot_data.timestamp().unix_timestamp() as u64, - ); - let finished_block_sink = self.block_sink_factory.create_builder_sink( - slot_data, - Arc::new(NullBestBidSource {}), - cancel.clone(), - ); - - let res = BlockFinisher::new(slot_bidder, Arc::from(finished_block_sink)); - Arc::new(res) - } -} diff --git a/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs b/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs new file mode 100644 index 00000000..59d41a5f --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs @@ -0,0 +1,163 @@ +use std::sync::Arc; + +use crate::{ + building::builders::{UnfinishedBlockBuildingSink, UnfinishedBlockBuildingSinkFactory}, + live_builder::payload_events::MevBoostSlotData, +}; +use alloy_primitives::U256; +use tracing::error; + +use super::{ + bid_value_source::interfaces::{BidValueObs, BidValueSource}, + bidding::{ + interfaces::{BiddingService, SlotBidder}, + sequential_sealer_bid_maker::SequentialSealerBidMaker, + wallet_balance_watcher::WalletBalanceWatcher, + }, + relay_submit::BuilderSinkFactory, +}; + +/// UnfinishedBlockBuildingSinkFactory to bid blocks against the competition. +/// Blocks are given to a SlotBidder (created per block). +/// SlotBidder bids using a SequentialSealerBidMaker (created per block). +/// SequentialSealerBidMaker sends the bids to a BlockBuildingSink (created per block). +/// SlotBidder is subscribed to the BidValueSource. +#[derive(Debug)] +pub struct BlockSealingBidderFactory { + /// Factory for the SlotBidder for blocks. + bidding_service: Box, + /// Factory for the final destination for blocks. + block_sink_factory: Box, + /// SlotBidder are subscribed to the proper block in the bid_value_source. + competition_bid_value_source: Arc, + wallet_balance_watcher: WalletBalanceWatcher, +} + +impl BlockSealingBidderFactory { + pub fn new( + bidding_service: Box, + block_sink_factory: Box, + competition_bid_value_source: Arc, + wallet_balance_watcher: WalletBalanceWatcher, + ) -> Self { + Self { + bidding_service, + block_sink_factory, + competition_bid_value_source, + wallet_balance_watcher, + } + } +} + +/// Struct to solve trait upcasting not supported in rust stable. +#[derive(Debug)] +struct SlotBidderToBidValueObs { + bidder: Arc, +} + +impl BidValueObs for SlotBidderToBidValueObs { + fn update_new_bid(&self, bid: U256) { + self.bidder.update_new_bid(bid); + } +} + +impl UnfinishedBlockBuildingSinkFactory for BlockSealingBidderFactory { + fn create_sink( + &mut self, + slot_data: MevBoostSlotData, + cancel: tokio_util::sync::CancellationToken, + ) -> std::sync::Arc { + match self + .wallet_balance_watcher + .update_to_block(slot_data.block() - 1) + { + Ok(landed_blocks) => self + .bidding_service + .update_new_landed_blocks_detected(&landed_blocks), + Err(error) => { + error!(error=?error, "Error updating wallet state"); + self.bidding_service + .update_failed_reading_new_landed_blocks() + } + } + + let finished_block_sink = self.block_sink_factory.create_builder_sink( + slot_data.clone(), + self.competition_bid_value_source.clone(), + cancel.clone(), + ); + let sealer = SequentialSealerBidMaker::new(Arc::from(finished_block_sink), cancel.clone()); + + let slot_bidder: Arc = self.bidding_service.create_slot_bidder( + slot_data.block(), + slot_data.slot(), + slot_data.timestamp(), + Box::new(sealer), + cancel.clone(), + ); + + let res = BlockSealingBidder::new( + slot_data, + slot_bidder, + self.competition_bid_value_source.clone(), + ); + + Arc::new(res) + } +} + +/// Helper object containing the bidder. +/// It just forwards new blocks and new competitions bids (via SlotBidderToBidValueObs) to the bidder. +#[derive(Debug)] +struct BlockSealingBidder { + /// Bidder we ask how to finish the blocks. + bid_value_source_to_unsubscribe: Arc, + /// Used to unsubscribe on drop. + competition_bid_value_source: Arc, + bidder: Arc, +} + +impl BlockSealingBidder { + pub fn new( + slot_data: MevBoostSlotData, + bidder: Arc, + competition_bid_value_source: Arc, + ) -> Self { + let slot_bidder_to_bid_value_obs: Arc = + Arc::new(SlotBidderToBidValueObs { + bidder: bidder.clone(), + }); + + competition_bid_value_source.subscribe( + slot_data.block(), + slot_data.slot(), + slot_bidder_to_bid_value_obs.clone(), + ); + + Self { + bid_value_source_to_unsubscribe: slot_bidder_to_bid_value_obs, + competition_bid_value_source, + bidder, + } + } +} + +impl UnfinishedBlockBuildingSink for BlockSealingBidder { + fn new_block( + &self, + block: Box, + ) { + self.bidder.new_block(block); + } + + fn can_use_suggested_fee_recipient_as_coinbase(&self) -> bool { + self.bidder.can_use_suggested_fee_recipient_as_coinbase() + } +} + +impl Drop for BlockSealingBidder { + fn drop(&mut self) { + self.competition_bid_value_source + .unsubscribe(self.bid_value_source_to_unsubscribe.clone()); + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/mod.rs b/crates/rbuilder/src/live_builder/block_output/mod.rs index fcd5de14..3c7c5f31 100644 --- a/crates/rbuilder/src/live_builder/block_output/mod.rs +++ b/crates/rbuilder/src/live_builder/block_output/mod.rs @@ -1,5 +1,5 @@ pub mod bid_observer; +pub mod bid_value_source; pub mod bidding; -mod block_finisher; -pub mod block_finisher_factory; +pub mod block_sealing_bidder_factory; pub mod relay_submit; diff --git a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs index 13100fb9..08e259e4 100644 --- a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs +++ b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs @@ -27,7 +27,10 @@ use tokio::time::{sleep, Instant}; use tokio_util::sync::CancellationToken; use tracing::{debug, error, event, info_span, trace, warn, Instrument, Level}; -use super::bid_observer::BidObserver; +use super::{ + bid_observer::BidObserver, + bid_value_source::{best_bid_sync_source::BestBidSyncSource, interfaces::BidValueSource}, +}; const SIM_ERROR_CATEGORY: &str = "submit_block_simulation"; const VALIDATION_ERROR_CATEGORY: &str = "validate_block_simulation"; @@ -76,20 +79,6 @@ pub trait BlockBuildingSink: std::fmt::Debug + Send + Sync { fn new_block(&self, block: Block); } -/// trait to get the best bid from the competition. -/// Used only by BuilderSinkFactory. -pub trait BestBidSource: Send + Sync { - fn best_bid_value(&self) -> Option; -} - -pub struct NullBestBidSource {} - -impl BestBidSource for NullBestBidSource { - fn best_bid_value(&self) -> Option { - None - } -} - /// Factory used to create BlockBuildingSink.. pub trait BuilderSinkFactory: std::fmt::Debug + Send + Sync { /// # Arguments @@ -97,7 +86,7 @@ pub trait BuilderSinkFactory: std::fmt::Debug + Send + Sync { fn create_builder_sink( &self, slot_data: MevBoostSlotData, - bid_source: Arc, + competition_bid_value_source: Arc, cancel: CancellationToken, ) -> Box; } @@ -146,8 +135,13 @@ async fn run_submit_to_relays_job( relays: Vec, config: Arc, cancel: CancellationToken, - bid_source: Arc, + competition_bid_value_source: Arc, ) -> Option { + let best_bid_sync_source = BestBidSyncSource::new( + competition_bid_value_source, + slot_data.block(), + slot_data.slot(), + ); let mut res = None; // first, sleep to slot time - slot_delta_to_start_submits { @@ -210,7 +204,7 @@ async fn run_submit_to_relays_job( .count(); let submission_optimistic = config.optimistic_enabled && block.trace.bid_value < config.optimistic_max_bid_value; - let best_bid_value = bid_source.best_bid_value().unwrap_or_default(); + let best_bid_value = best_bid_sync_source.best_bid_value().unwrap_or_default(); let submission_span = info_span!( "bid", bid_value = format_ether(block.trace.bid_value), @@ -359,7 +353,7 @@ pub async fn run_submit_to_relays_job_and_metrics( relays: Vec, config: Arc, cancel: CancellationToken, - bid_source: Arc, + competition_bid_value_source: Arc, ) { let best_bid = run_submit_to_relays_job( best_bid.clone(), @@ -367,7 +361,7 @@ pub async fn run_submit_to_relays_job_and_metrics( relays, config, cancel, - bid_source, + competition_bid_value_source, ) .await; if let Some(best_bid) = best_bid { @@ -543,7 +537,7 @@ impl BuilderSinkFactory for RelaySubmitSinkFactory { fn create_builder_sink( &self, slot_data: MevBoostSlotData, - bid_source: Arc, + competition_bid_value_source: Arc, cancel: CancellationToken, ) -> Box { let best_bid = BestBlockCell::default(); @@ -564,7 +558,7 @@ impl BuilderSinkFactory for RelaySubmitSinkFactory { relays, self.submission_config.clone(), cancel, - bid_source, + competition_bid_value_source, )); Box::new(best_bid) } diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index bb52632b..d8da970d 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -5,6 +5,12 @@ use super::{ base_config::BaseConfig, block_output::{ bid_observer::{BidObserver, NullBidObserver}, + bid_value_source::null_bid_value_source::NullBidValueSource, + bidding::{ + interfaces::BiddingService, true_block_value_bidder::TrueBlockValueBiddingService, + wallet_balance_watcher::WalletBalanceWatcher, + }, + block_sealing_bidder_factory::BlockSealingBidderFactory, relay_submit::{RelaySubmitSinkFactory, SubmissionConfig}, }, }; @@ -18,13 +24,8 @@ use crate::{ Sorting, }, live_builder::{ - base_config::EnvOrValue, - block_output::{ - bidding::DummyBiddingService, block_finisher_factory::BlockFinisherFactory, - relay_submit::BuilderSinkFactory, - }, - cli::LiveBuilderConfig, - payload_events::MevBoostSlotDataGenerator, + base_config::EnvOrValue, block_output::relay_submit::BuilderSinkFactory, + cli::LiveBuilderConfig, payload_events::MevBoostSlotDataGenerator, }, mev_boost::BLSBlockSigner, primitives::mev_boost::{MevBoostRelay, RelayConfig}, @@ -54,12 +55,16 @@ use std::{ path::{Path, PathBuf}, str::FromStr, sync::Arc, + time::Duration, }; use tracing::info; use url::Url; /// From experience (Vitaly's) all generated blocks before slot_time-8sec end loosing (due to last moment orders?) const DEFAULT_SLOT_DELTA_TO_START_SUBMITS: time::Duration = time::Duration::milliseconds(-8000); +/// We initialize the wallet with the last full day. This should be enough for any bidder. +/// On debug I measured this to be < 300ms so it's not big deal. +pub const WALLET_INIT_HISTORY_SIZE: Duration = Duration::from_secs(60 * 60 * 24); /// This example has a single building algorithm cfg but the idea of this enum is to have several builders #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] @@ -276,13 +281,25 @@ impl LiveBuilderConfig for Config { &self, cancellation_token: tokio_util::sync::CancellationToken, ) -> eyre::Result, MevBoostSlotDataGenerator>> { + let provider_factory = self.base_config.provider_factory()?; let (sink_sealed_factory, relays) = self.l1_config.create_relays_sealed_sink_factory( self.base_config.chain_spec()?, Box::new(NullBidObserver {}), )?; - let sink_factory = Box::new(BlockFinisherFactory::new( - Box::new(DummyBiddingService {}), + + let (wallet_balance_watcher, wallet_history) = WalletBalanceWatcher::new( + provider_factory.provider_factory_unchecked(), + self.base_config.coinbase_signer()?.address, + WALLET_INIT_HISTORY_SIZE, + )?; + let bidding_service: Box = + Box::new(TrueBlockValueBiddingService::new(&wallet_history)); + + let sink_factory = Box::new(BlockSealingBidderFactory::new( + bidding_service, sink_sealed_factory, + Arc::new(NullBidValueSource {}), + wallet_balance_watcher, )); let payload_event = MevBoostSlotDataGenerator::new( @@ -293,7 +310,12 @@ impl LiveBuilderConfig for Config { ); let live_builder = self .base_config - .create_builder(cancellation_token, sink_factory, payload_event) + .create_builder_with_provider_factory( + cancellation_token, + sink_factory, + payload_event, + provider_factory, + ) .await?; let root_hash_config = self.base_config.live_root_hash_config()?; let root_hash_task_pool = self.base_config.root_hash_task_pool()?; From 04ae7826a01d3d104d2dcd25c3aa087025ec2d95 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:18:10 -0300 Subject: [PATCH 18/30] Parallel sealing (#187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This PR replaces the SequentialSealerBidMaker for the ParallelSealerBidMaker to allow concurrent block sealing. ## 💡 Motivation and Context Inclution rate went down when we deployed the version using SequentialSealerBidMaker. ## ✅ I have completed the following steps: * [ X] Run `make lint` * [ X] Run `make test` * [ ] Added tests (if applicable) --- .../block_output/bidding/interfaces.rs | 2 +- .../live_builder/block_output/bidding/mod.rs | 1 + .../bidding/parallel_sealer_bid_maker.rs | 142 ++++++++++++++++++ .../block_sealing_bidder_factory.rs | 12 +- crates/rbuilder/src/live_builder/config.rs | 3 + 5 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 crates/rbuilder/src/live_builder/block_output/bidding/parallel_sealer_bid_maker.rs diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs b/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs index 35b61b97..3a74dbe5 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs @@ -51,7 +51,7 @@ impl Bid { } } -/// Makes the actual bid (send it to the relay) +/// Makes the actual bid (seal + send it to the relay). pub trait BidMaker: std::fmt::Debug { fn send_bid(&self, bid: Bid); } diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs b/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs index 65ae2418..bb0d0c89 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding/mod.rs @@ -1,4 +1,5 @@ pub mod interfaces; +pub mod parallel_sealer_bid_maker; pub mod sequential_sealer_bid_maker; pub mod true_block_value_bidder; pub mod wallet_balance_watcher; diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/parallel_sealer_bid_maker.rs b/crates/rbuilder/src/live_builder/block_output/bidding/parallel_sealer_bid_maker.rs new file mode 100644 index 00000000..b8e7ae9c --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/bidding/parallel_sealer_bid_maker.rs @@ -0,0 +1,142 @@ +use std::sync::{Arc, Mutex}; +use tokio::sync::Notify; +use tokio_util::sync::CancellationToken; +use tracing::error; + +use crate::live_builder::block_output::relay_submit::BlockBuildingSink; + +use super::interfaces::{Bid, BidMaker}; + +/// BidMaker with a background task sealing multiple parallel bids concurrently. +/// If several bids arrive while we hit the max of concurrent sealings we keep only the last one since we assume new is better. +#[derive(Debug)] +pub struct ParallelSealerBidMaker { + pending_bid: Arc, +} + +impl BidMaker for ParallelSealerBidMaker { + fn send_bid(&self, bid: Bid) { + self.pending_bid.update(bid); + } +} + +/// Object used to send new bids to the [ParallelSealerBidMakerProcess]. +#[derive(Debug)] +struct PendingBid { + /// Next bid to send. + bid: Mutex>, + /// Signaled when we set a new bid. + bid_notify: Arc, +} + +impl PendingBid { + fn new(bid_notify: Arc) -> Self { + Self { + bid: Default::default(), + bid_notify, + } + } + /// Updates bid, replacing on current (we assume they are always increasing but we don't check it). + fn update(&self, bid: Bid) { + let mut current_bid = self.bid.lock().unwrap(); + *current_bid = Some(bid); + self.bid_notify.notify_one(); + } + + fn consume_bid(&self) -> Option { + let mut current_bid = self.bid.lock().unwrap(); + current_bid.take() + } +} + +impl ParallelSealerBidMaker { + pub fn new( + max_concurrent_seals: usize, + sink: Arc, + cancel: CancellationToken, + ) -> Self { + let notify = Arc::new(Notify::new()); + let pending_bid = Arc::new(PendingBid::new(notify.clone())); + let mut sealing_process = ParallelSealerBidMakerProcess { + sink, + cancel, + pending_bid: pending_bid.clone(), + notify: notify.clone(), + seal_control: Arc::new(SealsInProgress { + notify, + seals_in_progress: Default::default(), + }), + max_concurrent_seals, + }; + + tokio::task::spawn(async move { + sealing_process.run().await; + }); + Self { pending_bid } + } +} + +struct SealsInProgress { + /// Signaled when a sealing finishes. + notify: Arc, + /// Number of current sealings in progress. + seals_in_progress: Mutex, +} + +/// Background task waiting for new bids to seal. +struct ParallelSealerBidMakerProcess { + /// Destination of the finished blocks. + sink: Arc, + cancel: CancellationToken, + pending_bid: Arc, + /// Signaled when we set a new bid or a sealing finishes. + notify: Arc, + /// Shared between the sealing tasks and the main loop. + seal_control: Arc, + /// Maximum number of concurrent sealings. + max_concurrent_seals: usize, +} + +impl ParallelSealerBidMakerProcess { + async fn run(&mut self) { + loop { + tokio::select! { + _ = self.wait_for_change() => self.check_for_new_bid().await, + _ = self.cancel.cancelled() => return + } + } + } + + async fn wait_for_change(&self) { + self.notify.notified().await + } + + /// block.finalize_block + self.sink.new_block inside spawn_blocking. + async fn check_for_new_bid(&mut self) { + if *self.seal_control.seals_in_progress.lock().unwrap() >= self.max_concurrent_seals { + return; + } + if let Some(bid) = self.pending_bid.consume_bid() { + let payout_tx_val = bid.payout_tx_value(); + let block = bid.block(); + let block_number = block.building_context().block(); + // Take sealing "slot" + *self.seal_control.seals_in_progress.lock().unwrap() += 1; + let seal_control = self.seal_control.clone(); + let sink = self.sink.clone(); + tokio::task::spawn_blocking(move || { + match block.finalize_block(payout_tx_val) { + Ok(res) => sink.new_block(res.block), + Err(error) => error!( + block_number, + ?error, + "Error on finalize_block on ParallelSealerBidMaker" + ), + }; + // release sealing "slot" + *seal_control.seals_in_progress.lock().unwrap() -= 1; + seal_control.notify.notify_one(); + }); + } + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs b/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs index 59d41a5f..9c90fbb1 100644 --- a/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs +++ b/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs @@ -11,7 +11,7 @@ use super::{ bid_value_source::interfaces::{BidValueObs, BidValueSource}, bidding::{ interfaces::{BiddingService, SlotBidder}, - sequential_sealer_bid_maker::SequentialSealerBidMaker, + parallel_sealer_bid_maker::ParallelSealerBidMaker, wallet_balance_watcher::WalletBalanceWatcher, }, relay_submit::BuilderSinkFactory, @@ -31,6 +31,8 @@ pub struct BlockSealingBidderFactory { /// SlotBidder are subscribed to the proper block in the bid_value_source. competition_bid_value_source: Arc, wallet_balance_watcher: WalletBalanceWatcher, + /// See [ParallelSealerBidMaker] + max_concurrent_seals: usize, } impl BlockSealingBidderFactory { @@ -39,12 +41,14 @@ impl BlockSealingBidderFactory { block_sink_factory: Box, competition_bid_value_source: Arc, wallet_balance_watcher: WalletBalanceWatcher, + max_concurrent_seals: usize, ) -> Self { Self { bidding_service, block_sink_factory, competition_bid_value_source, wallet_balance_watcher, + max_concurrent_seals, } } } @@ -86,7 +90,11 @@ impl UnfinishedBlockBuildingSinkFactory for BlockSealingBidderFactory { self.competition_bid_value_source.clone(), cancel.clone(), ); - let sealer = SequentialSealerBidMaker::new(Arc::from(finished_block_sink), cancel.clone()); + let sealer = ParallelSealerBidMaker::new( + self.max_concurrent_seals, + Arc::from(finished_block_sink), + cancel.clone(), + ); let slot_bidder: Arc = self.bidding_service.create_slot_bidder( slot_data.block(), diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index d8da970d..1daa675f 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -65,6 +65,8 @@ const DEFAULT_SLOT_DELTA_TO_START_SUBMITS: time::Duration = time::Duration::mill /// We initialize the wallet with the last full day. This should be enough for any bidder. /// On debug I measured this to be < 300ms so it's not big deal. pub const WALLET_INIT_HISTORY_SIZE: Duration = Duration::from_secs(60 * 60 * 24); +/// Number of sealing processes to run in parallel for each builder algorithm. +pub const SEALING_PROCESSES_PER_BUILDER_ALGORITHM: usize = 2; /// This example has a single building algorithm cfg but the idea of this enum is to have several builders #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] @@ -300,6 +302,7 @@ impl LiveBuilderConfig for Config { sink_sealed_factory, Arc::new(NullBidValueSource {}), wallet_balance_watcher, + SEALING_PROCESSES_PER_BUILDER_ALGORITHM * self.builders.len(), )); let payload_event = MevBoostSlotDataGenerator::new( From 00602cc9b97173000afcf78047a72667a3a67cb1 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:35:33 -0300 Subject: [PATCH 19/30] Make mod watchdog public. (#190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Allows reuse of the watchdog func. ## 💡 Motivation and Context I love to share. --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable) --- crates/rbuilder/src/live_builder/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rbuilder/src/live_builder/mod.rs b/crates/rbuilder/src/live_builder/mod.rs index aa6a5da6..7d5b6a24 100644 --- a/crates/rbuilder/src/live_builder/mod.rs +++ b/crates/rbuilder/src/live_builder/mod.rs @@ -6,7 +6,7 @@ pub mod config; pub mod order_input; pub mod payload_events; pub mod simulation; -mod watchdog; +pub mod watchdog; use crate::{ building::{ From 73629a2face0eeb18c0c5c6c5a79a62f25da7729 Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:08:02 -0300 Subject: [PATCH 20/30] New parameter for max concurrent seals (#192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Adds max_concurrent_seals to the cfg. 1 -> uses SequentialSealerBidMaker >1 -> uses ParallelSealerBidMaker(max_concurrent_seals) ## 💡 Motivation and Context Needed to polish the optimal cfg for the new roothash algo. --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [ ] Added tests (if applicable) --- config-live-example.toml | 2 ++ .../block_sealing_bidder_factory.rs | 22 +++++++++++++------ crates/rbuilder/src/live_builder/config.rs | 13 +++++++---- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/config-live-example.toml b/config-live-example.toml index 2b6836b2..b3c4f03e 100644 --- a/config-live-example.toml +++ b/config-live-example.toml @@ -27,6 +27,8 @@ dry_run_validation_url = "http://localhost:8545" ignore_cancellable_orders = true +max_concurrent_seals = 4 + sbundle_mergeabe_signers = [] # slot_delta_to_start_submits_ms is usually negative since we start bidding BEFORE the slot start # slot_delta_to_start_submits_ms = -5000 diff --git a/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs b/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs index 9c90fbb1..ece99d7c 100644 --- a/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs +++ b/crates/rbuilder/src/live_builder/block_output/block_sealing_bidder_factory.rs @@ -10,8 +10,9 @@ use tracing::error; use super::{ bid_value_source::interfaces::{BidValueObs, BidValueSource}, bidding::{ - interfaces::{BiddingService, SlotBidder}, + interfaces::{BidMaker, BiddingService, SlotBidder}, parallel_sealer_bid_maker::ParallelSealerBidMaker, + sequential_sealer_bid_maker::SequentialSealerBidMaker, wallet_balance_watcher::WalletBalanceWatcher, }, relay_submit::BuilderSinkFactory, @@ -90,17 +91,24 @@ impl UnfinishedBlockBuildingSinkFactory for BlockSealingBidderFactory { self.competition_bid_value_source.clone(), cancel.clone(), ); - let sealer = ParallelSealerBidMaker::new( - self.max_concurrent_seals, - Arc::from(finished_block_sink), - cancel.clone(), - ); + let sealer: Box = if self.max_concurrent_seals == 1 { + Box::new(SequentialSealerBidMaker::new( + Arc::from(finished_block_sink), + cancel.clone(), + )) + } else { + Box::new(ParallelSealerBidMaker::new( + self.max_concurrent_seals, + Arc::from(finished_block_sink), + cancel.clone(), + )) + }; let slot_bidder: Arc = self.bidding_service.create_slot_bidder( slot_data.block(), slot_data.slot(), slot_data.timestamp(), - Box::new(sealer), + sealer, cancel.clone(), ); diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index 1daa675f..b0112c5d 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -65,8 +65,8 @@ const DEFAULT_SLOT_DELTA_TO_START_SUBMITS: time::Duration = time::Duration::mill /// We initialize the wallet with the last full day. This should be enough for any bidder. /// On debug I measured this to be < 300ms so it's not big deal. pub const WALLET_INIT_HISTORY_SIZE: Duration = Duration::from_secs(60 * 60 * 24); -/// Number of sealing processes to run in parallel for each builder algorithm. -pub const SEALING_PROCESSES_PER_BUILDER_ALGORITHM: usize = 2; +/// 1 is easier for debugging. +pub const DEFAULT_MAX_CONCURRENT_SEALS: u64 = 1; /// This example has a single building algorithm cfg but the idea of this enum is to have several builders #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] @@ -117,9 +117,13 @@ pub struct L1Config { /// If true all optimistic submissions will be validated on nodes specified in `dry_run_validation_url` pub optimistic_prevalidate_optimistic_blocks: bool, - // See [`SubmissionConfig`] + /// See [`SubmissionConfig`] slot_delta_to_start_submits_ms: Option, + /// How many seals we are going to be doing in parallel. + /// Optimal value may change depending on the roothash computation caching strategies. + pub max_concurrent_seals: u64, + ///Name kept singular for backwards compatibility #[serde_as(deserialize_as = "OneOrMany>")] pub cl_node_url: Vec>, @@ -138,6 +142,7 @@ impl Default for L1Config { optimistic_prevalidate_optimistic_blocks: false, slot_delta_to_start_submits_ms: None, cl_node_url: vec![EnvOrValue::from("http://127.0.0.1:3500")], + max_concurrent_seals: DEFAULT_MAX_CONCURRENT_SEALS, } } } @@ -302,7 +307,7 @@ impl LiveBuilderConfig for Config { sink_sealed_factory, Arc::new(NullBidValueSource {}), wallet_balance_watcher, - SEALING_PROCESSES_PER_BUILDER_ALGORITHM * self.builders.len(), + self.l1_config.max_concurrent_seals as usize, )); let payload_event = MevBoostSlotDataGenerator::new( From 10495ea9ff3441da93792e9e0ee72abec74e24af Mon Sep 17 00:00:00 2001 From: Suyash Nayan <89125422+7suyash7@users.noreply.github.com> Date: Fri, 27 Sep 2024 19:23:57 +0530 Subject: [PATCH 21/30] feat: Allow for changing cached reads inside of BlockBuildingHelperFromDB (#189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #178 - Added `update_cached_reads` method to the `BlockBuildingHelper` trait - Implemented `update_cached_reads` for `BlockBuildingHelperFromDB` - Updated `MockBlockBuildingHelper` to include an unimplemented `update_cached_reads` method ## ✅ I have completed the following steps: * [ ✅] Run `make lint` * [✅ ] Run `make test` --------- Signed-off-by: 7suyash7 --- .../src/building/builders/block_building_helper.rs | 7 +++++++ .../src/building/builders/mock_block_building_helper.rs | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index 18559e97..806ca65e 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -74,6 +74,9 @@ pub trait BlockBuildingHelper: Send + Sync { /// BlockBuildingContext used for building. fn building_context(&self) -> &BlockBuildingContext; + + /// Updates the cached reads for the block state. + fn update_cached_reads(&mut self, cached_reads: CachedReads); } /// Implementation of BlockBuildingHelper based on a ProviderFactory @@ -386,4 +389,8 @@ impl BlockBuildingHelper for BlockBuildingHelper fn box_clone(&self) -> Box { Box::new(self.clone()) } + + fn update_cached_reads(&mut self, cached_reads: CachedReads) { + self.block_state = self.block_state.clone().with_cached_reads(cached_reads); + } } diff --git a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs index e0f295a1..3850a391 100644 --- a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs @@ -100,4 +100,8 @@ impl BlockBuildingHelper for MockBlockBuildingHelper { fn building_context(&self) -> &BlockBuildingContext { &self.block_building_context } + + fn update_cached_reads(&mut self, _cached_reads: CachedReads) { + unimplemented!() + } } From 01e0ab512fe84344258cd8168cc97b6999be35db Mon Sep 17 00:00:00 2001 From: Roman Krasiuk Date: Mon, 30 Sep 2024 10:36:36 +0200 Subject: [PATCH 22/30] feat: allow reading config path from env (#196) ## Description Allow reading config path from env. --- crates/rbuilder/src/live_builder/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rbuilder/src/live_builder/cli.rs b/crates/rbuilder/src/live_builder/cli.rs index 8547cd8f..aa30060e 100644 --- a/crates/rbuilder/src/live_builder/cli.rs +++ b/crates/rbuilder/src/live_builder/cli.rs @@ -29,7 +29,7 @@ enum Cli { #[derive(Parser, Debug)] struct RunCmd { - #[clap(help = "Config file path")] + #[clap(env = "RBUILDER_CONFIG", help = "Config file path")] config: PathBuf, } From 0c0985b27e27ace5938c32734c7a0e1c56876e66 Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Mon, 30 Sep 2024 13:21:24 +0200 Subject: [PATCH 23/30] Bundle hash for redistribution (#193) Adds bundle hash to redistribution output output json diff: ``` < "Bundle": { < "uuid": "$UUID", < "hash": "$HASH" < } --- > "Bundle": "$UUID" ``` --- .../rbuilder/src/backtest/redistribute/mod.rs | 108 ++++++++++++++---- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/crates/rbuilder/src/backtest/redistribute/mod.rs b/crates/rbuilder/src/backtest/redistribute/mod.rs index aed7f5db..5b9e3fb0 100644 --- a/crates/rbuilder/src/backtest/redistribute/mod.rs +++ b/crates/rbuilder/src/backtest/redistribute/mod.rs @@ -17,14 +17,15 @@ use ahash::{HashMap, HashSet}; use alloy_primitives::utils::format_ether; use alloy_primitives::{Address, B256, I256, U256}; pub use cli::run_backtest_redistribute; -use jsonrpsee::core::Serialize; use rayon::prelude::*; use reth_chainspec::ChainSpec; use reth_db::DatabaseEnv; use reth_provider::ProviderFactory; +use serde::{Deserialize, Serialize}; use std::cmp::{max, min}; use std::sync::Arc; use tracing::{debug, info, info_span, trace, warn}; +use uuid::Uuid; #[derive(Debug, Clone, Serialize)] #[serde(rename_all = "camelCase")] @@ -39,7 +40,7 @@ pub struct IdentityData { #[derive(Debug, Clone, Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderInclusionChange { - id: OrderId, + id: ExtendedOrderId, change: InclusionChange, #[serde(with = "u256decimal_serde_helper")] profit_before: U256, @@ -55,11 +56,34 @@ pub enum InclusionChange { ProfitChanged, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum ExtendedOrderId { + Tx(B256), + Bundle { uuid: Uuid, hash: B256 }, + ShareBundle(B256), +} + +impl ExtendedOrderId { + fn new(order_id: OrderId, bundle_hashes: &HashMap) -> Self { + match order_id { + OrderId::Tx(hash) => ExtendedOrderId::Tx(hash), + OrderId::Bundle(uuid) => { + let hash = bundle_hashes.get(&order_id).cloned().unwrap_or_default(); + ExtendedOrderId::Bundle { uuid, hash } + } + OrderId::ShareBundle(hash) => ExtendedOrderId::ShareBundle(hash), + } + } +} + #[derive(Debug, Clone, Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderData { - pub id: OrderId, + pub id: ExtendedOrderId, pub identity: Address, + /// `sender` is signer of the transaction when order has only 1 tx + /// otherwise its a signer of the request (e.g. eth_sendBundle) + pub sender: Address, #[serde(with = "u256decimal_serde_helper")] pub redistribution_value_received: U256, pub block_value_delta: I256, @@ -281,6 +305,8 @@ struct AvailableOrders { all_orders_by_address: HashMap>, orders_id_to_address: HashMap, all_orders_by_id: HashMap, + bundle_hash_by_id: HashMap, + order_sender_by_id: HashMap, } impl AvailableOrders { @@ -346,6 +372,8 @@ fn split_orders_by_identities( let mut all_orders_by_address: HashMap> = HashMap::default(); let mut included_orders_by_address: HashMap> = HashMap::default(); let mut orders_id_to_address = HashMap::default(); + let mut bundle_hash_by_id = HashMap::default(); + let mut order_sender_by_id = HashMap::default(); for order in &included_orders_available { let order_id = order.order.id(); @@ -364,6 +392,10 @@ fn split_orders_by_identities( for order in &block_data.available_orders { let id = order.order.id(); + if let Order::Bundle(bundle) = &order.order { + bundle_hash_by_id.insert(id, bundle.hash); + }; + order_sender_by_id.insert(id, order_sender(&order.order)); let address = match order_redistribution_address(&order.order, protect_signers) { Some(address) => address, None => { @@ -406,6 +438,8 @@ fn split_orders_by_identities( .iter() .map(|order| (order.order.id(), order.order.clone())) .collect(), + bundle_hash_by_id, + order_sender_by_id, } } @@ -769,11 +803,17 @@ fn collect_redistribution_result( "Included order data" ); result.landed_orders.push(OrderData { - id, + id: ExtendedOrderId::new(id, &available_orders.bundle_hash_by_id), identity: address, + sender: available_orders + .order_sender_by_id + .get(&id) + .cloned() + .unwrap_or_default(), redistribution_value_received, block_value_delta, inclusion_changes: calc_inclusion_change( + &available_orders.bundle_hash_by_id, result_after_order_exclusion, &results_without_exclusion.orders_included, ), @@ -795,6 +835,7 @@ fn collect_redistribution_result( redistribution_value_received, block_value_delta, inclusion_changes: calc_inclusion_change( + &available_orders.bundle_hash_by_id, result_after_identity_exclusion, &results_without_exclusion.orders_included, ), @@ -804,17 +845,21 @@ fn collect_redistribution_result( } fn calc_inclusion_change( + bundle_hash_by_id: &HashMap, exclusion_result: &ExclusionResult, included_before: &[(OrderId, U256)], ) -> Vec { let mut result = Vec::new(); for (id, profit_after) in &exclusion_result.new_orders_included { - result.push(OrderInclusionChange { - id: *id, - change: InclusionChange::Included, - profit_before: U256::ZERO, - profit_after: *profit_after, - }) + result.push(( + *id, + OrderInclusionChange { + id: ExtendedOrderId::new(*id, bundle_hash_by_id), + change: InclusionChange::Included, + profit_before: U256::ZERO, + profit_after: *profit_after, + }, + )); } for id in &exclusion_result.new_orders_failed { let profit_before = included_before @@ -822,12 +867,15 @@ fn calc_inclusion_change( .find(|(i, _)| i == id) .map(|(_, p)| *p) .unwrap_or_default(); - result.push(OrderInclusionChange { - id: *id, - change: InclusionChange::Excluded, - profit_before, - profit_after: U256::ZERO, - }) + result.push(( + *id, + OrderInclusionChange { + id: ExtendedOrderId::new(*id, bundle_hash_by_id), + change: InclusionChange::Excluded, + profit_before, + profit_after: U256::ZERO, + }, + )); } for (id, profit_after) in &exclusion_result.orders_profit_changed { let profit_before = included_before @@ -835,15 +883,18 @@ fn calc_inclusion_change( .find(|(i, _)| i == id) .map(|(_, p)| *p) .unwrap_or_default(); - result.push(OrderInclusionChange { - id: *id, - change: InclusionChange::ProfitChanged, - profit_before, - profit_after: *profit_after, - }) + result.push(( + *id, + OrderInclusionChange { + id: ExtendedOrderId::new(*id, bundle_hash_by_id), + change: InclusionChange::ProfitChanged, + profit_before, + profit_after: *profit_after, + }, + )) } - result.sort_by_key(|k| k.id); - result + result.sort_by_key(|(id, _)| *id); + result.into_iter().map(|(_, v)| v).collect() } #[derive(Debug)] @@ -984,3 +1035,12 @@ fn order_redistribution_address(order: &Order, protect_signers: &[Address]) -> O } } } + +fn order_sender(order: &Order) -> Address { + let mut txs = order.list_txs(); + if txs.len() == 1 { + return txs.pop().unwrap().0.signer(); + } + + order.signer().unwrap_or_default() +} From cc8b8c3d87f482bbb0df1da76a112811ea009620 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Mon, 30 Sep 2024 15:46:16 +0200 Subject: [PATCH 24/30] chore: bump rust version to 1.81 (#197) 1.79 no longer compiles. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4ab98ff1..a908c3e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ # # Based on https://depot.dev/blog/rust-dockerfile-best-practices # -FROM rust:1.79 as base +FROM rust:1.81 as base ARG FEATURES From 66756ad9f1ac8c116774d630dffde0923d000f4f Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:08:07 -0400 Subject: [PATCH 25/30] chore: bump keccak-asm, sha3-asm (#198) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This updates sha3-asm / keccak-asm deps. ## 💡 Motivation and Context `0.1.4` includes fixes which make keccak-asm work on more platforms (https://github.com/DaniPopes/keccak-asm/pull/5) --- ## ✅ I have completed the following steps: * [ ] Run `make lint` * [ ] Run `make test` * [ ] Added tests (if applicable) --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb1aa429..04c41732 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4692,9 +4692,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -10407,9 +10407,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" dependencies = [ "cc", "cfg-if", From c886cf1278e8f12e459adaeaef5f58b12515e8ee Mon Sep 17 00:00:00 2001 From: Roman Krasiuk Date: Mon, 30 Sep 2024 18:28:38 +0200 Subject: [PATCH 26/30] feat: pectra (#183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Support for the upcoming Pectra hardfork. Depends on https://github.com/alloy-rs/alloy/pull/1303 --- Cargo.lock | 19 ++++--- Cargo.toml | 2 +- crates/rbuilder/src/building/mod.rs | 34 +++++++++--- crates/rbuilder/src/mev_boost/mod.rs | 10 +++- crates/rbuilder/src/mev_boost/sign_payload.rs | 54 +++++++++++++++---- crates/rbuilder/src/validation_api_client.rs | 1 + 6 files changed, 93 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04c41732..0f2a5cd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.3.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "499ee14d296a133d142efd215eb36bf96124829fe91cf8f5d4e5ccdd381eae00" +checksum = "f923dd5fca5f67a43d81ed3ebad0880bd41f6dd0ada930030353ac356c54cd0f" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -464,9 +464,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "0.3.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abbd9b6764423821bd6874477791ca68cfd0e946958d611319b57b006edf0113" +checksum = "2e7081d2206dca51ce23a06338d78d9b536931cc3f15134fc1c6535eb2b77f18" dependencies = [ "alloy-eips", "alloy-primitives 0.8.0", @@ -480,23 +480,22 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.3.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d79cadb52e32d40afa04847647eb50a332559d7870e66e46a0c32c33bf1c801d" +checksum = "1464c4dd646e1bdfde86ae65ce5ba168dbb29180b478011fe87117ae46b1629b" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-primitives 0.8.0", "alloy-rlp", - "alloy-rpc-types-eth", "alloy-serde", + "derive_more 1.0.0", "ethereum_ssz", "ethereum_ssz_derive", "jsonrpsee-types 0.24.3", "jsonwebtoken", "rand 0.8.5", "serde", - "thiserror", ] [[package]] @@ -4828,7 +4827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -5664,7 +5663,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 2.0.72", diff --git a/Cargo.toml b/Cargo.toml index cf448b64..c6390ed3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,4 +74,4 @@ alloy-rpc-types-engine = { version = "0.3.0", features = [ "ssz", ] } alloy-rpc-types-eth = { version = "0.3.0" } -alloy-signer-local = { version = "0.3.0" } \ No newline at end of file +alloy-signer-local = { version = "0.3.0" } diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index 491e51f8..43c15123 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -36,7 +36,8 @@ use reth_basic_payload_builder::{commit_withdrawals, WithdrawalsOutcome}; use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_errors::ProviderError; use reth_evm::system_calls::{ - post_block_withdrawal_requests_contract_call, pre_block_beacon_root_contract_call, + post_block_consolidation_requests_contract_call, post_block_withdrawal_requests_contract_call, + pre_block_beacon_root_contract_call, pre_block_blockhashes_contract_call, }; use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, revm_spec, EthEvmConfig}; use reth_node_api::PayloadBuilderAttributes; @@ -581,18 +582,30 @@ impl PartialBlock { .chain_spec .is_prague_active_at_timestamp(ctx.attributes.timestamp()) { - let deposit_requests = - parse_deposits_from_receipts(&ctx.chain_spec, self.receipts.iter())?; + let evm_config = EthEvmConfig::default(); let mut db = state.new_db_ref(); + let deposit_requests = + parse_deposits_from_receipts(&ctx.chain_spec, self.receipts.iter())?; let withdrawal_requests = post_block_withdrawal_requests_contract_call( - &EthEvmConfig::default(), + &evm_config, + db.as_mut(), + &ctx.initialized_cfg, + &ctx.block_env, + )?; + let consolidation_requests = post_block_consolidation_requests_contract_call( + &evm_config, db.as_mut(), &ctx.initialized_cfg, &ctx.block_env, )?; - let requests = [deposit_requests, withdrawal_requests].concat(); + let requests = [ + deposit_requests, + withdrawal_requests, + consolidation_requests, + ] + .concat(); let requests_root = calculate_requests_root(&requests); (Some(requests.into()), Some(requests_root)) } else { @@ -706,15 +719,24 @@ impl PartialBlock { ctx: &BlockBuildingContext, state: &mut BlockState, ) -> eyre::Result<()> { + let evm_config = EthEvmConfig::default(); let mut db = state.new_db_ref(); pre_block_beacon_root_contract_call( db.as_mut(), - &EthEvmConfig::default(), + &evm_config, &ctx.chain_spec, &ctx.initialized_cfg, &ctx.block_env, ctx.attributes.parent_beacon_block_root(), )?; + pre_block_blockhashes_contract_call( + db.as_mut(), + &evm_config, + &ctx.chain_spec, + &ctx.initialized_cfg, + &ctx.block_env, + ctx.attributes.parent, + )?; db.as_mut().merge_transitions(BundleRetention::Reverts); Ok(()) } diff --git a/crates/rbuilder/src/mev_boost/mod.rs b/crates/rbuilder/src/mev_boost/mod.rs index 28a0d149..e968b442 100644 --- a/crates/rbuilder/src/mev_boost/mod.rs +++ b/crates/rbuilder/src/mev_boost/mod.rs @@ -6,7 +6,9 @@ pub mod sign_payload; use super::utils::u256decimal_serde_helper; use alloy_primitives::{Address, BlockHash, Bytes, U256}; -use alloy_rpc_types_beacon::relay::{BidTrace, SignedBidSubmissionV2, SignedBidSubmissionV3}; +use alloy_rpc_types_beacon::relay::{ + BidTrace, SignedBidSubmissionV2, SignedBidSubmissionV3, SignedBidSubmissionV4, +}; use flate2::{write::GzEncoder, Compression}; use primitive_types::H384; use reqwest::{ @@ -455,6 +457,7 @@ impl RelayClient { match data { SubmitBlockRequest::Capella(data) => data.0.as_ssz_bytes(), SubmitBlockRequest::Deneb(data) => data.0.as_ssz_bytes(), + SubmitBlockRequest::Electra(data) => data.0.as_ssz_bytes(), }, SSZ_CONTENT_TYPE, ) @@ -582,6 +585,9 @@ impl RelayClient { } } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct ElectraSubmitBlockRequest(SignedBidSubmissionV4); + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct DenebSubmitBlockRequest(SignedBidSubmissionV3); @@ -599,6 +605,7 @@ pub struct CapellaSubmitBlockRequest(SignedBidSubmissionV2); pub enum SubmitBlockRequest { Capella(CapellaSubmitBlockRequest), Deneb(DenebSubmitBlockRequest), + Electra(ElectraSubmitBlockRequest), } impl SubmitBlockRequest { @@ -606,6 +613,7 @@ impl SubmitBlockRequest { match self { SubmitBlockRequest::Capella(req) => req.0.message.clone(), SubmitBlockRequest::Deneb(req) => req.0.message.clone(), + SubmitBlockRequest::Electra(req) => req.0.message.clone(), } } } diff --git a/crates/rbuilder/src/mev_boost/sign_payload.rs b/crates/rbuilder/src/mev_boost/sign_payload.rs index 313d7887..acf56dee 100644 --- a/crates/rbuilder/src/mev_boost/sign_payload.rs +++ b/crates/rbuilder/src/mev_boost/sign_payload.rs @@ -1,12 +1,15 @@ -use super::{CapellaSubmitBlockRequest, DenebSubmitBlockRequest, SubmitBlockRequest}; +use super::{ + CapellaSubmitBlockRequest, DenebSubmitBlockRequest, ElectraSubmitBlockRequest, + SubmitBlockRequest, +}; use crate::utils::u256decimal_serde_helper; use alloy_primitives::{Address, BlockHash, FixedBytes, B256, U256}; use alloy_rpc_types_beacon::{ - relay::{BidTrace, SignedBidSubmissionV2, SignedBidSubmissionV3}, + relay::{BidTrace, SignedBidSubmissionV2, SignedBidSubmissionV3, SignedBidSubmissionV4}, BlsPublicKey, }; use alloy_rpc_types_engine::{ - BlobsBundleV1, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, + BlobsBundleV1, ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, ExecutionPayloadV4, }; use alloy_rpc_types_eth::Withdrawal; use ethereum_consensus::{ @@ -178,12 +181,45 @@ pub fn sign_block_for_relay( let blobs_bundle = marshal_txs_blobs_sidecars(blobs_bundle); - SubmitBlockRequest::Deneb(DenebSubmitBlockRequest(SignedBidSubmissionV3 { - message, - execution_payload, - blobs_bundle: blobs_bundle.clone(), - signature, - })) + if chain_spec.is_prague_active_at_timestamp(sealed_block.timestamp) { + let mut deposit_requests = Vec::new(); + let mut withdrawal_requests = Vec::new(); + let mut consolidation_requests = Vec::new(); + for request in sealed_block.requests.iter().flat_map(|r| &r.0) { + match request { + alloy_consensus::Request::DepositRequest(r) => { + deposit_requests.push(*r); + } + alloy_consensus::Request::WithdrawalRequest(r) => { + withdrawal_requests.push(*r); + } + alloy_consensus::Request::ConsolidationRequest(r) => { + consolidation_requests.push(*r); + } + _ => {} + }; + } + + let execution_payload = ExecutionPayloadV4 { + payload_inner: execution_payload, + deposit_requests, + withdrawal_requests, + consolidation_requests, + }; + SubmitBlockRequest::Electra(ElectraSubmitBlockRequest(SignedBidSubmissionV4 { + message, + execution_payload, + blobs_bundle, + signature, + })) + } else { + SubmitBlockRequest::Deneb(DenebSubmitBlockRequest(SignedBidSubmissionV3 { + message, + execution_payload, + blobs_bundle, + signature, + })) + } } else { let execution_payload = capella_payload; SubmitBlockRequest::Capella(CapellaSubmitBlockRequest(SignedBidSubmissionV2 { diff --git a/crates/rbuilder/src/validation_api_client.rs b/crates/rbuilder/src/validation_api_client.rs index 797fbd40..ce668db3 100644 --- a/crates/rbuilder/src/validation_api_client.rs +++ b/crates/rbuilder/src/validation_api_client.rs @@ -77,6 +77,7 @@ impl ValidationAPIClient { let method = match req { SubmitBlockRequest::Capella(_) => "flashbots_validateBuilderSubmissionV2", SubmitBlockRequest::Deneb(_) => "flashbots_validateBuilderSubmissionV3", + SubmitBlockRequest::Electra(_) => "flashbots_validateBuilderSubmissionV4", }; let request = ValidRequest { req: req.clone(), From dc58de5565293f8b2a914256b0e2e79cc48e173a Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Tue, 1 Oct 2024 19:36:36 +0200 Subject: [PATCH 27/30] Don't consider profit too low and consistent db err as errors. (#202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary Currently we log errors that can happen normally * profit too low (that happens if we don't have enough eth on coinbase yet) * consisent db view error (that happens if block that we are building for is proposed) ## ✅ I have completed the following steps: * [ ] Run `make lint` * [ ] Run `make test` * [ ] Added tests (if applicable) --- .../builders/block_building_helper.rs | 28 +++++++++---- crates/rbuilder/src/building/mod.rs | 40 +++++++++++++++---- .../bidding/sequential_sealer_bid_maker.rs | 14 ++++--- crates/rbuilder/src/roothash/mod.rs | 20 +++++++++- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index 806ca65e..8f0295c7 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -17,8 +17,8 @@ use crate::{ building::{ estimate_payout_gas_limit, tracers::GasUsedSimulationTracer, BlockBuildingContext, BlockState, BuiltBlockTrace, BuiltBlockTraceError, CriticalCommitOrderError, - EstimatePayoutGasErr, ExecutionError, ExecutionResult, FinalizeResult, PartialBlock, - Sorting, + EstimatePayoutGasErr, ExecutionError, ExecutionResult, FinalizeError, FinalizeResult, + PartialBlock, Sorting, }, primitives::SimulatedOrder, roothash::RootHashConfig, @@ -115,12 +115,27 @@ pub enum BlockBuildingHelperError { InsertPayoutTxErr(#[from] crate::building::InsertPayoutTxErr), #[error("Bundle consistency check failed: {0}")] BundleConsistencyCheckFailed(#[from] BuiltBlockTraceError), - #[error("Error finalizing block (eg:root hash): {0}")] - FinalizeError(#[from] eyre::Report), + #[error("Error finalizing block: {0}")] + FinalizeError(#[from] FinalizeError), #[error("Payout tx not allowed for block")] PayoutTxNotAllowed, } +impl BlockBuildingHelperError { + /// Non critial error can happen during normal operations of the builder + pub fn is_critical(&self) -> bool { + match self { + BlockBuildingHelperError::FinalizeError(finalize) => { + !finalize.is_consistent_db_view_err() + } + BlockBuildingHelperError::InsertPayoutTxErr( + crate::building::InsertPayoutTxErr::ProfitTooLow, + ) => false, + _ => true, + } + } +} + pub struct FinalizeBlockResult { pub block: Block, /// Since finalize_block eats the object we need the cached_reads in case we create a new @@ -333,10 +348,7 @@ impl BlockBuildingHelper for BlockBuildingHelper ) { Ok(finalized_block) => finalized_block, Err(err) => { - if err - .to_string() - .contains("failed to initialize consistent view") - { + if err.is_consistent_db_view_err() { let last_block_number = self .provider_factory .last_block_number() diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index 43c15123..ba6b5c57 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -16,7 +16,7 @@ use reth_primitives::proofs::calculate_requests_root; use crate::{ primitives::{Order, OrderId, SimValue, SimulatedOrder, TransactionSignedEcRecoveredWithBlobs}, - roothash::{calculate_state_root, RootHashConfig}, + roothash::{calculate_state_root, RootHashConfig, RootHashError}, utils::{a2r_withdrawal, calc_gas_limit, timestamp_as_u64, Signer}, }; use ahash::HashSet; @@ -409,6 +409,24 @@ pub struct FinalizeResult { pub txs_blob_sidecars: Vec>, } +#[derive(Debug, thiserror::Error)] +pub enum FinalizeError { + #[error("Root hash error: {0:?}")] + RootHash(#[from] RootHashError), + #[error("Other error: {0:?}")] + Other(#[from] eyre::Report), +} + +impl FinalizeError { + /// see `RootHashError::is_consistent_db_view_err` + pub fn is_consistent_db_view_err(&self) -> bool { + match self { + FinalizeError::RootHash(root_hash) => root_hash.is_consistent_db_view_err(), + FinalizeError::Other(_) => false, + } + } +} + impl PartialBlock { pub fn with_tracer( self, @@ -562,7 +580,7 @@ impl PartialBlock { provider_factory: ProviderFactory, root_hash_config: RootHashConfig, root_hash_task_pool: BlockingTaskPool, - ) -> eyre::Result { + ) -> Result { let (withdrawals_root, withdrawals) = { let mut db = state.new_db_ref(); let WithdrawalsOutcome { @@ -573,7 +591,8 @@ impl PartialBlock { &ctx.chain_spec, ctx.attributes.timestamp, ctx.attributes.withdrawals.clone(), - )?; + ) + .map_err(|err| FinalizeError::Other(err.into()))?; db.as_mut().merge_transitions(PlainState); (withdrawals_root, withdrawals) }; @@ -586,19 +605,22 @@ impl PartialBlock { let mut db = state.new_db_ref(); let deposit_requests = - parse_deposits_from_receipts(&ctx.chain_spec, self.receipts.iter())?; + parse_deposits_from_receipts(&ctx.chain_spec, self.receipts.iter()) + .map_err(|err| FinalizeError::Other(err.into()))?; let withdrawal_requests = post_block_withdrawal_requests_contract_call( &evm_config, db.as_mut(), &ctx.initialized_cfg, &ctx.block_env, - )?; + ) + .map_err(|err| FinalizeError::Other(err.into()))?; let consolidation_requests = post_block_consolidation_requests_contract_call( &evm_config, db.as_mut(), &ctx.initialized_cfg, &ctx.block_env, - )?; + ) + .map_err(|err| FinalizeError::Other(err.into()))?; let requests = [ deposit_requests, @@ -647,11 +669,13 @@ impl PartialBlock { // double check blocked txs for tx_with_blob in &self.executed_tx { if ctx.blocklist.contains(&tx_with_blob.signer()) { - return Err(eyre::eyre!("To from blocked address.")); + return Err(FinalizeError::Other(eyre::eyre!( + "To from blocked address." + ))); } if let Some(to) = tx_with_blob.to() { if ctx.blocklist.contains(&to) { - return Err(eyre::eyre!("Tx to blocked address")); + return Err(FinalizeError::Other(eyre::eyre!("Tx to blocked address"))); } } } diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs b/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs index 8018aa86..3c729cb7 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding/sequential_sealer_bid_maker.rs @@ -95,11 +95,15 @@ impl SequentialSealerBidMakerProcess { match tokio::task::spawn_blocking(move || block.finalize_block(payout_tx_val)).await { Ok(finalize_res) => match finalize_res { Ok(res) => self.sink.new_block(res.block), - Err(error) => error!( - block_number, - ?error, - "Error on finalize_block on SequentialSealerBidMaker" - ), + Err(error) => { + if error.is_critical() { + error!( + block_number, + ?error, + "Error on finalize_block on SequentialSealerBidMaker" + ) + } + } }, Err(error) => error!( block_number, diff --git a/crates/rbuilder/src/roothash/mod.rs b/crates/rbuilder/src/roothash/mod.rs index 859b7ea0..e88b8ebd 100644 --- a/crates/rbuilder/src/roothash/mod.rs +++ b/crates/rbuilder/src/roothash/mod.rs @@ -1,12 +1,14 @@ use alloy_primitives::B256; use eth_sparse_mpt::reth_sparse_trie::{ - calculate_root_hash_with_sparse_trie, SparseTrieError, SparseTrieSharedCache, + calculate_root_hash_with_sparse_trie, trie_fetcher::FetchNodeError, SparseTrieError, + SparseTrieSharedCache, }; use reth::{ providers::{providers::ConsistentDbView, ExecutionOutcome, ProviderFactory}, tasks::pool::BlockingTaskPool, }; use reth_db::database::Database; +use reth_errors::ProviderError; use reth_trie_parallel::async_root::{AsyncStateRoot, AsyncStateRootError}; use tracing::trace; @@ -33,6 +35,22 @@ pub enum RootHashError { Verification, } +impl RootHashError { + /// Error of this type means that db does not have trie for the required block + /// This often happens when building for block after it was proposed. + pub fn is_consistent_db_view_err(&self) -> bool { + let provider_error = match self { + RootHashError::AsyncStateRoot(AsyncStateRootError::Provider(p)) => p, + RootHashError::SparseStateRoot(SparseTrieError::FetchNode( + FetchNodeError::Provider(p), + )) => p, + _ => return false, + }; + + matches!(provider_error, ProviderError::ConsistentView(_)) + } +} + #[derive(Debug, Clone)] pub struct RootHashConfig { pub mode: RootHashMode, From 412ff880b939030e81ea068eb2cd8ee4fffe79ba Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 2 Oct 2024 16:33:57 +0100 Subject: [PATCH 28/30] Add option to supply genesis fork version from config (#203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary This PR adds the option to supply the genesis fork version from a flag instead of querying the CL nodes which might not be active yet. Closes https://github.com/flashbots/rbuilder/pull/35 ## 💡 Motivation and Context --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [x] Added tests (if applicable) --- config-live-example.toml | 2 + crates/rbuilder/src/live_builder/config.rs | 72 ++++++++++++++++------ 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/config-live-example.toml b/config-live-example.toml index b3c4f03e..020db91a 100644 --- a/config-live-example.toml +++ b/config-live-example.toml @@ -29,6 +29,8 @@ ignore_cancellable_orders = true max_concurrent_seals = 4 +# genesis_fork_version = "0x00112233" + sbundle_mergeabe_signers = [] # slot_delta_to_start_submits_ms is usually negative since we start bidding BEFORE the slot start # slot_delta_to_start_submits_ms = -5000 diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index b0112c5d..36eac698 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -127,6 +127,9 @@ pub struct L1Config { ///Name kept singular for backwards compatibility #[serde_as(deserialize_as = "OneOrMany>")] pub cl_node_url: Vec>, + + /// Genesis fork version for the chain. If not provided it will be fetched from the beacon client. + pub genesis_fork_version: Option, } impl Default for L1Config { @@ -143,6 +146,7 @@ impl Default for L1Config { slot_delta_to_start_submits_ms: None, cl_node_url: vec![EnvOrValue::from("http://127.0.0.1:3500")], max_concurrent_seals: DEFAULT_MAX_CONCURRENT_SEALS, + genesis_fork_version: None, } } } @@ -171,7 +175,11 @@ impl L1Config { } fn bls_signer(&self, chain_spec: &ChainSpec) -> eyre::Result { - let signing_domain = get_signing_domain(chain_spec.chain, self.beacon_clients()?)?; + let signing_domain = get_signing_domain( + chain_spec.chain, + self.beacon_clients()?, + self.genesis_fork_version.clone(), + )?; let secret_key = self.relay_secret_key.value()?; let secret_key = SecretKey::try_from(secret_key) .map_err(|e| eyre::eyre!("Failed to parse relay key: {:?}", e.to_string()))?; @@ -180,7 +188,11 @@ impl L1Config { } fn bls_optimistic_signer(&self, chain_spec: &ChainSpec) -> eyre::Result { - let signing_domain = get_signing_domain(chain_spec.chain, self.beacon_clients()?)?; + let signing_domain = get_signing_domain( + chain_spec.chain, + self.beacon_clients()?, + self.genesis_fork_version.clone(), + )?; let secret_key = self.optimistic_relay_secret_key.value()?; let secret_key = SecretKey::try_from(secret_key).map_err(|e| { eyre::eyre!("Failed to parse optimistic relay key: {:?}", e.to_string()) @@ -492,26 +504,34 @@ fn create_builder( } } -fn get_signing_domain(chain: Chain, beacon_clients: Vec) -> eyre::Result { +fn get_signing_domain( + chain: Chain, + beacon_clients: Vec, + genesis_fork_version: Option, +) -> eyre::Result { let cl_context = match chain.kind() { ChainKind::Named(NamedChain::Mainnet) => ContextEth::for_mainnet(), ChainKind::Named(NamedChain::Sepolia) => ContextEth::for_sepolia(), ChainKind::Named(NamedChain::Goerli) => ContextEth::for_goerli(), ChainKind::Named(NamedChain::Holesky) => ContextEth::for_holesky(), _ => { - let client = beacon_clients - .first() - .ok_or_else(|| eyre::eyre!("No beacon clients provided"))?; - - let spec = tokio::task::block_in_place(|| { - tokio::runtime::Handle::current().block_on(client.get_spec()) - })?; - - let genesis_fork_version = spec - .get("GENESIS_FORK_VERSION") - .ok_or_else(|| eyre::eyre!("GENESIS_FORK_VERSION not found in spec"))?; - - let version: FixedBytes<4> = FixedBytes::from_str(genesis_fork_version) + let genesis_fork_version = if let Some(genesis_fork_version) = genesis_fork_version { + genesis_fork_version + } else { + let client = beacon_clients + .first() + .ok_or_else(|| eyre::eyre!("No beacon clients provided"))?; + + let spec = tokio::task::block_in_place(|| { + tokio::runtime::Handle::current().block_on(client.get_spec()) + })?; + + spec.get("GENESIS_FORK_VERSION") + .ok_or_else(|| eyre::eyre!("GENESIS_FORK_VERSION not found in spec"))? + .clone() + }; + + let version: FixedBytes<4> = FixedBytes::from_str(&genesis_fork_version) .map_err(|e| eyre::eyre!("Failed to parse genesis fork version: {:?}", e))?; let version = Version::from(version); @@ -616,16 +636,32 @@ mod test { ]; for (chain, domain) in cases.iter() { - let found = get_signing_domain(Chain::from_named(*chain), vec![]).unwrap(); + let found = get_signing_domain(Chain::from_named(*chain), vec![], None).unwrap(); assert_eq!(found, *domain); } } + #[test] + fn test_signing_domain_with_genesis_fork() { + let client = Client::new(Url::parse("http://localhost:8000").unwrap()); + let found = get_signing_domain( + Chain::from_id(12345), + vec![client], + Some("0x00112233".to_string()), + ) + .unwrap(); + + assert_eq!( + found, + fixed_bytes!("0000000157eb3d0fd9a819dee70b5403ce939a22b4f25ec3fc841a16cc4eab3e") + ); + } + #[ignore] #[test] fn test_signing_domain_custom_chain() { let client = Client::new(Url::parse("http://localhost:8000").unwrap()); - let found = get_signing_domain(Chain::from_id(12345), vec![client]).unwrap(); + let found = get_signing_domain(Chain::from_id(12345), vec![client], None).unwrap(); assert_eq!( found, From 83e0b647aad7abc166d964c16d77ed90e0febadc Mon Sep 17 00:00:00 2001 From: ZanCorDX <126988525+ZanCorDX@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:16:29 -0300 Subject: [PATCH 29/30] More bidding mocks (#208) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary More mocking and debug stuff. ## 💡 Motivation and Context Allow better tests! --- ## ✅ I have completed the following steps: * [X] Run `make lint` * [X] Run `make test` * [ ] Added tests (if applicable) --- .../live_builder/block_output/bid_value_source/interfaces.rs | 2 ++ .../src/live_builder/block_output/bidding/interfaces.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs b/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs index a936770b..aba71d2b 100644 --- a/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs +++ b/crates/rbuilder/src/live_builder/block_output/bid_value_source/interfaces.rs @@ -1,7 +1,9 @@ use alloy_primitives::U256; +use mockall::automock; use std::sync::Arc; /// Sync + Send to allow to be called from another thread. +#[automock] pub trait BidValueObs: std::fmt::Debug + Sync + Send { /// @Pending: add source of the bid. fn update_new_bid(&self, bid: U256); diff --git a/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs b/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs index 3a74dbe5..f108161f 100644 --- a/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs +++ b/crates/rbuilder/src/live_builder/block_output/bidding/interfaces.rs @@ -5,6 +5,7 @@ use crate::{ live_builder::block_output::bid_value_source::interfaces::BidValueObs, }; use alloy_primitives::U256; +use mockall::automock; use reth_primitives::BlockNumber; use time::OffsetDateTime; use tokio_util::sync::CancellationToken; @@ -57,6 +58,7 @@ pub trait BidMaker: std::fmt::Debug { } /// Info about a onchain block from reth. +#[derive(Eq, PartialEq, Clone, Debug)] pub struct LandedBlockInfo { pub block_number: BlockNumber, pub block_timestamp: OffsetDateTime, @@ -95,6 +97,7 @@ pub trait BiddingService: std::fmt::Debug + Send + Sync { /// Trait to control the must_win_block feature of the BiddingService. /// It allows to use BiddingService as a Box (single threaded mutable access) but be able to call must_win_block from another thread. +#[automock] pub trait BiddingServiceWinControl: Send + Sync + std::fmt::Debug { /// If called, any current or future SlotBidder working on that block will bid more aggressively to win the block. fn must_win_block(&self, block: u64); From 6cf6b28b414e51f3eb9b43e2f5aedc73b81c9392 Mon Sep 17 00:00:00 2001 From: Vitaly Drogan Date: Thu, 3 Oct 2024 19:24:39 +0200 Subject: [PATCH 30/30] Fix metric panic (#209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary ## 💡 Motivation and Context --- ## ✅ I have completed the following steps: * [ ] Run `make lint` * [ ] Run `make test` * [ ] Added tests (if applicable) --- crates/rbuilder/src/telemetry/metrics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rbuilder/src/telemetry/metrics.rs b/crates/rbuilder/src/telemetry/metrics.rs index 4f3d3eae..fb933f97 100644 --- a/crates/rbuilder/src/telemetry/metrics.rs +++ b/crates/rbuilder/src/telemetry/metrics.rs @@ -89,7 +89,7 @@ register_metrics! { pub static BLOCK_VALIDATION_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("block_validation_time", "Block Validation Times (ms)") .buckets(exponential_buckets_range(1.0, 3000.0, 100)), - &["builder_name"] + &[] ) .unwrap(); pub static CURRENT_BLOCK: IntGauge =