From f803134231ebfc7ade1897f1a3fd421897a99d58 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 31 Dec 2024 15:45:36 +0100 Subject: [PATCH] Add block list struct --- .../src/backtest/backtest_build_block.rs | 2 +- .../src/backtest/backtest_build_range.rs | 2 +- crates/rbuilder/src/backtest/execute.rs | 6 +- .../rbuilder/src/backtest/redistribute/mod.rs | 2 +- .../resim_landed_block.rs | 4 +- crates/rbuilder/src/blocklist/mod.rs | 147 ++++++++++++++++++ .../src/blocklist/testdata/blocklist.txt | 5 + .../src/building/built_block_trace.rs | 5 +- crates/rbuilder/src/building/mod.rs | 8 +- .../src/building/testing/bundle_tests/mod.rs | 12 +- .../src/building/testing/test_chain_state.rs | 7 +- crates/rbuilder/src/lib.rs | 1 + .../rbuilder/src/live_builder/base_config.rs | 11 +- crates/rbuilder/src/live_builder/config.rs | 2 +- crates/rbuilder/src/live_builder/mod.rs | 4 +- .../src/live_builder/payload_events/mod.rs | 8 +- 16 files changed, 189 insertions(+), 37 deletions(-) create mode 100644 crates/rbuilder/src/blocklist/mod.rs create mode 100644 crates/rbuilder/src/blocklist/testdata/blocklist.txt diff --git a/crates/rbuilder/src/backtest/backtest_build_block.rs b/crates/rbuilder/src/backtest/backtest_build_block.rs index 5d0953bb..c5775dfb 100644 --- a/crates/rbuilder/src/backtest/backtest_build_block.rs +++ b/crates/rbuilder/src/backtest/backtest_build_block.rs @@ -107,7 +107,7 @@ where provider_factory.clone(), chain_spec.clone(), cli.block_building_time_ms, - config.base_config().blocklist()?, + config.base_config().blocklist_file_path.clone(), &config.base_config().sbundle_mergeable_signers(), config.base_config().coinbase_signer()?, )?; diff --git a/crates/rbuilder/src/backtest/backtest_build_range.rs b/crates/rbuilder/src/backtest/backtest_build_range.rs index da96d7f3..16b32eed 100644 --- a/crates/rbuilder/src/backtest/backtest_build_range.rs +++ b/crates/rbuilder/src/backtest/backtest_build_range.rs @@ -133,7 +133,7 @@ where None }; - let blocklist = config.base_config().blocklist()?; + let blocklist = config.base_config().blocklist_file_path.clone(); let mut read_blocks = spawn_block_fetcher( historical_data_storage, diff --git a/crates/rbuilder/src/backtest/execute.rs b/crates/rbuilder/src/backtest/execute.rs index 053d8bb5..1971ac92 100644 --- a/crates/rbuilder/src/backtest/execute.rs +++ b/crates/rbuilder/src/backtest/execute.rs @@ -1,5 +1,6 @@ use crate::{ backtest::BlockData, + blocklist::BlockList, building::{ builders::BacktestSimulateBlockInput, multi_share_bundle_merger::MultiShareBundleMerger, sim::simulate_all_orders_with_sim_tree, BlockBuildingContext, BundleErr, OrderErr, @@ -9,7 +10,6 @@ use crate::{ primitives::{OrderId, SimulatedOrder}, utils::{clean_extradata, Signer}, }; -use ahash::HashSet; use alloy_primitives::{Address, U256}; use reth::revm::cached::CachedReads; use reth_chainspec::ChainSpec; @@ -61,7 +61,7 @@ pub fn backtest_prepare_ctx_for_block

( provider: P, chain_spec: Arc, build_block_lag_ms: i64, - blocklist: HashSet

, + blocklist: BlockList, sbundle_mergeabe_signers: &[Address], builder_signer: Signer, ) -> eyre::Result @@ -114,7 +114,7 @@ pub fn backtest_simulate_block( build_block_lag_ms: i64, builders_names: Vec, config: &ConfigType, - blocklist: HashSet
, + blocklist: BlockList, sbundle_mergeabe_signers: &[Address], ) -> eyre::Result where diff --git a/crates/rbuilder/src/backtest/redistribute/mod.rs b/crates/rbuilder/src/backtest/redistribute/mod.rs index 1d26a940..514ca994 100644 --- a/crates/rbuilder/src/backtest/redistribute/mod.rs +++ b/crates/rbuilder/src/backtest/redistribute/mod.rs @@ -1009,7 +1009,7 @@ where built_block_lag_ms, base_config.backtest_builders.clone(), config, - base_config.blocklist()?, + base_config.blocklist_file_path.clone(), &base_config.sbundle_mergeable_signers(), )? .builder_outputs 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 5f570f9b..9933d25e 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 @@ -5,7 +5,7 @@ use crate::{ }, utils::{extract_onchain_block_txs, find_suggested_fee_recipient, signed_uint_delta}, }; -use ahash::{HashMap, HashSet}; +use ahash::HashMap; use alloy_primitives::{TxHash, B256, I256}; use eyre::Context; use reth_chainspec::ChainSpec; @@ -46,7 +46,7 @@ where onchain_block, chain_spec, None, - HashSet::default(), + Default::default(), coinbase, suggested_fee_recipient, None, diff --git a/crates/rbuilder/src/blocklist/mod.rs b/crates/rbuilder/src/blocklist/mod.rs new file mode 100644 index 00000000..bcbf4361 --- /dev/null +++ b/crates/rbuilder/src/blocklist/mod.rs @@ -0,0 +1,147 @@ +use ahash::{HashSet, HashSetExt}; +use alloy_primitives::Address; +use serde::{Deserialize, Deserializer}; +use std::fs::read_to_string; +use std::path::PathBuf; + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct BlockList { + list: HashSet
, +} + +impl BlockList { + fn new() -> Self { + Self { + list: HashSet::new(), + } + } + + fn from_file(path: PathBuf) -> eyre::Result { + let blocklist_file = read_to_string(path)?; + let blocklist: Vec
= serde_json::from_str(&blocklist_file)?; + + Ok(Self { + list: blocklist.into_iter().collect(), + }) + } + + pub fn len(&self) -> usize { + self.list.len() + } + + pub fn contains(&self, address: &Address) -> bool { + self.list.contains(address) + } + + #[cfg(test)] + fn add(&mut self, address: Address) { + self.list.insert(address); + } +} + +impl From for BlockList { + fn from(path: PathBuf) -> Self { + Self::from_file(path).unwrap_or_else(|_| Self::new()) + } +} + +impl From> for BlockList { + fn from(addresses: Vec
) -> Self { + Self { + list: addresses.into_iter().collect(), + } + } +} + +impl<'de> Deserialize<'de> for BlockList { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let path: Option = Option::deserialize(deserializer)?; + + match path { + Some(path) => BlockList::from_file(path).map_err(serde::de::Error::custom), + None => Ok(BlockList::new()), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use alloy_primitives::{address, Address}; + use serde::Deserialize; + + #[test] + fn test_read_blocklist_from_file() { + let block_list = BlockList::from_file( + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/blocklist/testdata/blocklist.txt"), + ) + .unwrap(); + + let addr0 = address!("14dC79964da2C08b23698B3D3cc7Ca32193d9955"); + assert_eq!(block_list.contains(&addr0), true); + + let addr1 = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); + assert_eq!(block_list.contains(&addr1), true); + + let addr2 = address!("a0Ee7A142d267C1f36714E4a8F75612F20a79720"); + assert_eq!(block_list.contains(&addr2), false); + } + + #[test] + fn test_blocklist() { + let mut blocklist = BlockList::new(); + let addr0 = Address::random(); + + blocklist.add(addr0); + assert_eq!(blocklist.len(), 1); + assert_eq!(blocklist.contains(&addr0), true); + + // you cannot add twice the same value + blocklist.add(addr0); + assert_eq!(blocklist.len(), 1); + + let addr1 = Address::random(); + assert_eq!(blocklist.contains(&addr1), false); + + blocklist.add(addr1); + assert_eq!(blocklist.len(), 2); + assert_eq!(blocklist.contains(&addr1), true); + } + + #[derive(Deserialize)] + struct Config { + block_list: BlockList, + } + + #[test] + fn test_deserialize_config() { + let config_str = r#" + block_list = "src/blocklist/testdata/blocklist.txt" + "#; + let config: Config = toml::from_str(config_str).unwrap(); + assert_eq!(config.block_list.len(), 3); + + let addr1 = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); + assert_eq!(config.block_list.contains(&addr1), true); + + let empty_config_str = r#""#; + let config: Config = toml::from_str(empty_config_str).unwrap(); + assert_eq!(config.block_list.len(), 0); + } + + #[test] + fn test_from_vec() { + let addr0 = address!("14dC79964da2C08b23698B3D3cc7Ca32193d9955"); + let addr1 = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); + + let addresses = vec![addr0, addr1]; + let blocklist = BlockList::from(addresses); + + assert_eq!(blocklist.len(), 2); + assert_eq!(blocklist.contains(&addr0), true); + assert_eq!(blocklist.contains(&addr1), true); + } +} diff --git a/crates/rbuilder/src/blocklist/testdata/blocklist.txt b/crates/rbuilder/src/blocklist/testdata/blocklist.txt new file mode 100644 index 00000000..5d1884d3 --- /dev/null +++ b/crates/rbuilder/src/blocklist/testdata/blocklist.txt @@ -0,0 +1,5 @@ +[ + "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", + "f39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +] \ No newline at end of file diff --git a/crates/rbuilder/src/building/built_block_trace.rs b/crates/rbuilder/src/building/built_block_trace.rs index 2a2b809d..b5af5439 100644 --- a/crates/rbuilder/src/building/built_block_trace.rs +++ b/crates/rbuilder/src/building/built_block_trace.rs @@ -1,7 +1,8 @@ use super::{BundleErr, ExecutionError, ExecutionResult, OrderErr}; +use crate::blocklist::BlockList; use crate::primitives::{Order, OrderId, OrderReplacementKey}; use ahash::{HashMap, HashSet}; -use alloy_primitives::{Address, TxHash, U256}; +use alloy_primitives::{TxHash, U256}; use std::{collections::hash_map, time::Duration}; use time::OffsetDateTime; @@ -91,7 +92,7 @@ impl BuiltBlockTrace { pub fn verify_bundle_consistency( &self, - blocklist: &HashSet
, + blocklist: &BlockList, ) -> Result<(), BuiltBlockTraceError> { let mut replacement_data_count: HashSet<_> = HashSet::default(); let mut bundle_txs_scratchpad = HashMap::default(); diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index 7f59bf0e..855432e6 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -18,11 +18,11 @@ use reth_primitives::BlockBody; use reth_provider::{BlockReader, DatabaseProviderFactory, StateProviderFactory}; use crate::{ + blocklist::BlockList, primitives::{Order, OrderId, SimValue, SimulatedOrder, TransactionSignedEcRecoveredWithBlobs}, roothash::{calculate_state_root, RootHashConfig, RootHashError}, utils::{a2r_withdrawal, calc_gas_limit, timestamp_as_u64, Signer}, }; -use ahash::HashSet; use alloy_eips::{ calc_excess_blob_gas, eip4844::BlobTransactionSidecar, eip4895::Withdrawals, eip7685::Requests, merge::BEACON_NONCE, @@ -78,7 +78,7 @@ pub struct BlockBuildingContext { /// None: coinbase = attributes.suggested_fee_recipient. No payoffs allowed. /// Some(signer): coinbase = signer. pub builder_signer: Option, - pub blocklist: HashSet
, + pub blocklist: BlockList, pub extra_data: Vec, /// Excess blob gas calculated from the parent block header pub excess_blob_gas: Option, @@ -96,7 +96,7 @@ impl BlockBuildingContext { parent: &Header, signer: Signer, chain_spec: Arc, - blocklist: HashSet
, + blocklist: BlockList, prefer_gas_limit: Option, extra_data: Vec, spec_id: Option, @@ -173,7 +173,7 @@ impl BlockBuildingContext { onchain_block: alloy_rpc_types::Block, chain_spec: Arc, spec_id: Option, - blocklist: HashSet
, + blocklist: BlockList, coinbase: Address, suggested_fee_recipient: Address, builder_signer: Option, diff --git a/crates/rbuilder/src/building/testing/bundle_tests/mod.rs b/crates/rbuilder/src/building/testing/bundle_tests/mod.rs index 6a3bef50..b1babd22 100644 --- a/crates/rbuilder/src/building/testing/bundle_tests/mod.rs +++ b/crates/rbuilder/src/building/testing/bundle_tests/mod.rs @@ -2,10 +2,10 @@ pub mod setup; use alloy_primitives::{Address, B256, U256}; use itertools::Itertools; -use std::collections::HashSet; use uuid::Uuid; use crate::{ + blocklist::BlockList, building::{testing::bundle_tests::setup::NonceValue, BuiltBlockTrace, BundleErr, OrderErr}, primitives::{ Bundle, BundleReplacementData, BundleReplacementKey, Order, OrderId, Refund, RefundConfig, @@ -462,7 +462,7 @@ fn test_mev_share_failed_refunds() -> eyre::Result<()> { fn test_bundle_consistency_check() -> eyre::Result<()> { let mut test_setup = TestSetup::gen_test_setup(BlockArgs::default().number(11))?; - let blocklist = HashSet::default(); + let blocklist = BlockList::default(); // check revertible tx detection { let mut built_block_trace = BuiltBlockTrace::new(); @@ -522,9 +522,7 @@ fn test_bundle_consistency_check() -> eyre::Result<()> { // check commit of blocklisted tx from { - let blocklist = vec![test_setup.named_address(NamedAddr::User(0))?] - .into_iter() - .collect(); + let blocklist = BlockList::from(vec![test_setup.named_address(NamedAddr::User(0))?]); let mut built_block_trace = BuiltBlockTrace::new(); test_setup.begin_bundle_order(11); @@ -540,9 +538,7 @@ fn test_bundle_consistency_check() -> eyre::Result<()> { // check commit of blocklisted tx to { - let blocklist = vec![test_setup.named_address(NamedAddr::User(1))?] - .into_iter() - .collect(); + let blocklist = BlockList::from(vec![test_setup.named_address(NamedAddr::User(1))?]); let mut built_block_trace = BuiltBlockTrace::new(); test_setup.begin_bundle_order(11); diff --git a/crates/rbuilder/src/building/testing/test_chain_state.rs b/crates/rbuilder/src/building/testing/test_chain_state.rs index 507ca25d..9e5c4cf8 100644 --- a/crates/rbuilder/src/building/testing/test_chain_state.rs +++ b/crates/rbuilder/src/building/testing/test_chain_state.rs @@ -1,4 +1,3 @@ -use ahash::HashSet; use alloy_consensus::{Header, TxEip1559}; use alloy_primitives::{ keccak256, utils::parse_ether, Address, BlockHash, Bytes, TxKind as TransactionKind, B256, B64, @@ -17,7 +16,7 @@ use reth_provider::test_utils::{create_test_provider_factory, MockNodeTypesWithD use revm_primitives::SpecId; use std::sync::Arc; -use crate::{building::BlockBuildingContext, utils::Signer}; +use crate::{blocklist::BlockList, building::BlockBuildingContext, utils::Signer}; #[derive(Debug, Clone, Copy)] pub enum NamedAddr { @@ -233,7 +232,7 @@ struct TestBlockContextBuilder { parent_gas_used: u64, parent_hash: BlockHash, chain_spec: Arc, - blocklist: HashSet
, + blocklist: BlockList, prefer_gas_limit: Option, use_suggested_fee_recipient_as_coinbase: bool, } @@ -260,7 +259,7 @@ impl TestBlockContextBuilder { parent_gas_used: 15_000_000, parent_hash, chain_spec, - blocklist: vec![blocklisted].into_iter().collect(), + blocklist: BlockList::from(vec![blocklisted]), prefer_gas_limit: None, use_suggested_fee_recipient_as_coinbase: block_args .use_suggested_fee_recipient_as_coinbase, diff --git a/crates/rbuilder/src/lib.rs b/crates/rbuilder/src/lib.rs index 7572d559..0d7aca1e 100644 --- a/crates/rbuilder/src/lib.rs +++ b/crates/rbuilder/src/lib.rs @@ -1,5 +1,6 @@ pub mod backtest; pub mod beacon_api_client; +pub mod blocklist; pub mod building; pub mod integration; pub mod live_builder; diff --git a/crates/rbuilder/src/live_builder/base_config.rs b/crates/rbuilder/src/live_builder/base_config.rs index 21a3b8e8..d9d72514 100644 --- a/crates/rbuilder/src/live_builder/base_config.rs +++ b/crates/rbuilder/src/live_builder/base_config.rs @@ -1,13 +1,13 @@ //! Config should always be deserializable, default values should be used //! use crate::{ + blocklist::BlockList, building::builders::UnfinishedBlockBuildingSinkFactory, live_builder::{order_input::OrderInputConfig, LiveBuilder}, roothash::RootHashConfig, telemetry::{setup_reloadable_tracing_subscriber, LoggerConfig}, utils::{http_provider, BoxedProvider, ProviderFactoryReopener, Signer}, }; -use ahash::HashSet; use alloy_primitives::{Address, B256}; use eyre::{eyre, Context}; use jsonrpsee::RpcModule; @@ -76,7 +76,7 @@ pub struct BaseConfig { pub reth_db_path: Option, pub reth_static_files_path: Option, - pub blocklist_file_path: Option, + pub blocklist_file_path: BlockList, pub extra_data: String, /// mev-share bundles coming from this address are treated in a special way(see [`ShareBundleMerger`]) @@ -223,7 +223,7 @@ impl BaseConfig { coinbase_signer: self.coinbase_signer()?, extra_data: self.extra_data()?, - blocklist: self.blocklist()?, + blocklist: self.blocklist_file_path.clone(), global_cancellation: cancellation_token, @@ -308,6 +308,7 @@ impl BaseConfig { Ok(extra_data) } +<<<<<<< Updated upstream pub fn blocklist(&self) -> eyre::Result> { if let Some(path) = &self.blocklist_file_path { let blocklist_file = read_to_string(path).context("blocklist file")?; @@ -328,6 +329,8 @@ impl BaseConfig { } } +======= +>>>>>>> Stashed changes pub fn eth_rpc_provider(&self) -> eyre::Result { Ok(http_provider(self.backtest_fetch_eth_rpc_url.parse()?)) } @@ -449,7 +452,7 @@ impl Default for BaseConfig { reth_datadir: Some(DEFAULT_RETH_DB_PATH.parse().unwrap()), reth_db_path: None, reth_static_files_path: None, - blocklist_file_path: None, + blocklist_file_path: Default::default(), extra_data: "extra_data_change_me".to_string(), root_hash_use_sparse_trie: false, root_hash_compare_sparse_trie: false, diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index bf17e5c0..e76b20f8 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -327,7 +327,7 @@ impl LiveBuilderConfig for Config { let payload_event = MevBoostSlotDataGenerator::new( self.l1_config.beacon_clients()?, relays, - self.base_config.blocklist()?, + self.base_config.blocklist_file_path.clone(), cancellation_token.clone(), ); let live_builder = self diff --git a/crates/rbuilder/src/live_builder/mod.rs b/crates/rbuilder/src/live_builder/mod.rs index ff6ede4e..24b07946 100644 --- a/crates/rbuilder/src/live_builder/mod.rs +++ b/crates/rbuilder/src/live_builder/mod.rs @@ -9,6 +9,7 @@ pub mod simulation; pub mod watchdog; use crate::{ + blocklist::BlockList, building::{ builders::{BlockBuildingAlgorithm, UnfinishedBlockBuildingSinkFactory}, BlockBuildingContext, @@ -23,7 +24,6 @@ use crate::{ error_storage::spawn_error_storage_writer, provider_head_state::ProviderHeadState, Signer, }, }; -use ahash::HashSet; use alloy_consensus::Header; use alloy_primitives::{Address, B256}; use building::BlockBuildingPool; @@ -102,7 +102,7 @@ where pub coinbase_signer: Signer, pub extra_data: Vec, - pub blocklist: HashSet
, + pub blocklist: BlockList, pub global_cancellation: CancellationToken, diff --git a/crates/rbuilder/src/live_builder/payload_events/mod.rs b/crates/rbuilder/src/live_builder/payload_events/mod.rs index d1285f08..afcbbd4a 100644 --- a/crates/rbuilder/src/live_builder/payload_events/mod.rs +++ b/crates/rbuilder/src/live_builder/payload_events/mod.rs @@ -7,6 +7,7 @@ pub mod relay_epoch_cache; use crate::{ beacon_api_client::Client, + blocklist::BlockList, live_builder::{ payload_events::{ payload_source::PayloadSourceMuxer, @@ -16,7 +17,6 @@ use crate::{ }, primitives::mev_boost::{MevBoostRelay, MevBoostRelayID}, }; -use ahash::HashSet; use alloy_eips::merge::SLOT_DURATION; use alloy_primitives::{utils::format_ether, Address, B256, U256}; use alloy_rpc_types_beacon::events::PayloadAttributesEvent; @@ -81,7 +81,7 @@ impl MevBoostSlotData { pub struct MevBoostSlotDataGenerator { cls: Vec, relays: Vec, - blocklist: HashSet
, + blocklist: BlockList, global_cancellation: CancellationToken, } @@ -90,7 +90,7 @@ impl MevBoostSlotDataGenerator { pub fn new( cls: Vec, relays: Vec, - blocklist: HashSet
, + blocklist: BlockList, global_cancellation: CancellationToken, ) -> Self { Self { @@ -192,7 +192,7 @@ impl SlotSource for MevBoostSlotDataGenerator { fn check_slot_data_for_blocklist( data: &MevBoostSlotData, - blocklist: &HashSet
, + blocklist: &BlockList, ) -> eyre::Result<()> { if blocklist.contains(&data.fee_recipient()) { return Err(eyre::eyre!(