1 Commits

Author SHA1 Message Date
f109130f88 feat(draft): Spot meta 2025-11-05 04:07:46 +00:00
17 changed files with 96 additions and 139 deletions

View File

@ -1,5 +1,5 @@
pub mod call_forwarder; pub mod call_forwarder;
pub mod hl_node_compliance; pub mod hl_node_compliance;
pub mod subscribe_fixup;
pub mod tx_forwarder; pub mod tx_forwarder;
pub mod subscribe_fixup;
mod utils; mod utils;

View File

@ -1,10 +1,7 @@
pub mod hl; pub mod hl;
pub mod parser; pub mod parser;
use crate::{ use crate::{hardforks::HlHardforks, node::primitives::{header::HlHeaderExtras, HlHeader}};
hardforks::HlHardforks,
node::primitives::{HlHeader, header::HlHeaderExtras},
};
use alloy_eips::eip7840::BlobParams; use alloy_eips::eip7840::BlobParams;
use alloy_genesis::Genesis; use alloy_genesis::Genesis;
use alloy_primitives::{Address, B256, U256}; use alloy_primitives::{Address, B256, U256};

View File

@ -41,11 +41,8 @@ fn main() -> eyre::Result<()> {
ext: HlNodeArgs| async move { ext: HlNodeArgs| async move {
let default_upstream_rpc_url = builder.config().chain.official_rpc_url(); let default_upstream_rpc_url = builder.config().chain.official_rpc_url();
let (node, engine_handle_tx) = HlNode::new( let (node, engine_handle_tx) =
ext.block_source_args.parse().await?, HlNode::new(ext.block_source_args.parse().await?, ext.debug_cutoff_height);
ext.debug_cutoff_height,
ext.allow_network_overrides,
);
let NodeHandle { node, node_exit_future: exit_future } = builder let NodeHandle { node, node_exit_future: exit_future } = builder
.node(node) .node(node)
.extend_rpc_modules(move |mut ctx| { .extend_rpc_modules(move |mut ctx| {

View File

@ -1,8 +1,12 @@
use crate::{ use crate::{
chainspec::{HlChainSpec, parser::HlChainSpecParser}, chainspec::{HlChainSpec, parser::HlChainSpecParser},
node::{ node::{
HlNode, consensus::HlConsensus, evm::config::HlEvmConfig, migrate::Migrator, HlNode,
spot_meta::init as spot_meta_init, storage::tables::Tables, consensus::HlConsensus,
evm::config::HlEvmConfig,
migrate::Migrator,
spot_meta::init as spot_meta_init,
storage::tables::Tables,
}, },
pseudo_peer::BlockSourceArgs, pseudo_peer::BlockSourceArgs,
}; };
@ -20,10 +24,7 @@ use reth_cli::chainspec::ChainSpecParser;
use reth_cli_commands::{common::EnvironmentArgs, launcher::FnLauncher}; use reth_cli_commands::{common::EnvironmentArgs, launcher::FnLauncher};
use reth_db::{DatabaseEnv, init_db, mdbx::init_db_for}; use reth_db::{DatabaseEnv, init_db, mdbx::init_db_for};
use reth_tracing::FileWorkerGuard; use reth_tracing::FileWorkerGuard;
use std::{ use std::{fmt::{self}, sync::Arc};
fmt::{self},
sync::Arc,
};
use tracing::info; use tracing::info;
macro_rules! not_applicable { macro_rules! not_applicable {
@ -82,13 +83,6 @@ pub struct HlNodeArgs {
/// * Refers to the Merkle trie used for eth_getProof and state root, not actual state values. /// * Refers to the Merkle trie used for eth_getProof and state root, not actual state values.
#[arg(long, env = "EXPERIMENTAL_ETH_GET_PROOF")] #[arg(long, env = "EXPERIMENTAL_ETH_GET_PROOF")]
pub experimental_eth_get_proof: bool, pub experimental_eth_get_proof: bool,
/// Allow network configuration overrides from CLI.
///
/// When enabled, network settings (discovery_addr, listener_addr, dns_discovery, nat)
/// will be taken from CLI arguments instead of being hardcoded to localhost-only defaults.
#[arg(long, env = "ALLOW_NETWORK_OVERRIDES")]
pub allow_network_overrides: bool,
} }
/// The main reth_hl cli interface. /// The main reth_hl cli interface.

View File

@ -1,8 +1,4 @@
use crate::{ use crate::{hardforks::HlHardforks, node::{primitives::HlHeader, HlNode}, HlBlock, HlBlockBody, HlPrimitives};
HlBlock, HlBlockBody, HlPrimitives,
hardforks::HlHardforks,
node::{HlNode, primitives::HlHeader},
};
use reth::{ use reth::{
api::{FullNodeTypes, NodeTypes}, api::{FullNodeTypes, NodeTypes},
beacon_consensus::EthBeaconConsensus, beacon_consensus::EthBeaconConsensus,

View File

@ -1,6 +1,5 @@
use crate::{ use crate::{
HlBlock, HlHeader, node::evm::config::{HlBlockExecutorFactory, HlEvmConfig}, HlBlock, HlHeader
node::evm::config::{HlBlockExecutorFactory, HlEvmConfig},
}; };
use reth_evm::{ use reth_evm::{
block::BlockExecutionError, block::BlockExecutionError,

View File

@ -270,8 +270,8 @@ impl<'a, N: HlNodeType> MigrateStaticFiles<'a, N> {
let mut first = true; let mut first = true;
for (block_range, _tx_ranges) in all_static_files { for (block_range, _tx_ranges) in all_static_files {
let migration_needed = self.using_old_header(block_range.start())? || let migration_needed = self.using_old_header(block_range.start())?
self.using_old_header(block_range.end())?; || self.using_old_header(block_range.end())?;
if !migration_needed { if !migration_needed {
// Create a placeholder symlink // Create a placeholder symlink
self.create_placeholder(block_range)?; self.create_placeholder(block_range)?;

View File

@ -51,14 +51,12 @@ pub struct HlNode {
engine_handle_rx: Arc<Mutex<Option<oneshot::Receiver<ConsensusEngineHandle<HlPayloadTypes>>>>>, engine_handle_rx: Arc<Mutex<Option<oneshot::Receiver<ConsensusEngineHandle<HlPayloadTypes>>>>>,
block_source_config: BlockSourceConfig, block_source_config: BlockSourceConfig,
debug_cutoff_height: Option<u64>, debug_cutoff_height: Option<u64>,
allow_network_overrides: bool,
} }
impl HlNode { impl HlNode {
pub fn new( pub fn new(
block_source_config: BlockSourceConfig, block_source_config: BlockSourceConfig,
debug_cutoff_height: Option<u64>, debug_cutoff_height: Option<u64>,
allow_network_overrides: bool,
) -> (Self, oneshot::Sender<ConsensusEngineHandle<HlPayloadTypes>>) { ) -> (Self, oneshot::Sender<ConsensusEngineHandle<HlPayloadTypes>>) {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
( (
@ -66,7 +64,6 @@ impl HlNode {
engine_handle_rx: Arc::new(Mutex::new(Some(rx))), engine_handle_rx: Arc::new(Mutex::new(Some(rx))),
block_source_config, block_source_config,
debug_cutoff_height, debug_cutoff_height,
allow_network_overrides,
}, },
tx, tx,
) )
@ -98,7 +95,6 @@ impl HlNode {
engine_handle_rx: self.engine_handle_rx.clone(), engine_handle_rx: self.engine_handle_rx.clone(),
block_source_config: self.block_source_config.clone(), block_source_config: self.block_source_config.clone(),
debug_cutoff_height: self.debug_cutoff_height, debug_cutoff_height: self.debug_cutoff_height,
allow_network_overrides: self.allow_network_overrides,
}) })
.consensus(HlConsensusBuilder::default()) .consensus(HlConsensusBuilder::default())
} }

View File

@ -179,7 +179,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{HlHeader, chainspec::hl::hl_mainnet}; use crate::{chainspec::hl::hl_mainnet, HlHeader};
use super::*; use super::*;
use alloy_primitives::{B256, U128}; use alloy_primitives::{B256, U128};

View File

@ -25,10 +25,7 @@ use reth_network::{NetworkConfig, NetworkHandle, NetworkManager};
use reth_network_api::PeersInfo; use reth_network_api::PeersInfo;
use reth_provider::StageCheckpointReader; use reth_provider::StageCheckpointReader;
use reth_stages_types::StageId; use reth_stages_types::StageId;
use std::{ use std::sync::Arc;
net::{Ipv4Addr, SocketAddr},
sync::Arc,
};
use tokio::sync::{Mutex, mpsc, oneshot}; use tokio::sync::{Mutex, mpsc, oneshot};
use tracing::info; use tracing::info;
@ -147,8 +144,6 @@ pub struct HlNetworkBuilder {
pub(crate) block_source_config: BlockSourceConfig, pub(crate) block_source_config: BlockSourceConfig,
pub(crate) debug_cutoff_height: Option<u64>, pub(crate) debug_cutoff_height: Option<u64>,
pub(crate) allow_network_overrides: bool,
} }
impl HlNetworkBuilder { impl HlNetworkBuilder {
@ -179,24 +174,15 @@ impl HlNetworkBuilder {
ImportService::new(consensus, handle, from_network, to_network).await.unwrap(); ImportService::new(consensus, handle, from_network, to_network).await.unwrap();
}); });
let mut config_builder = ctx.network_config_builder()?; Ok(ctx.build_network_config(
ctx.network_config_builder()?
// Only apply localhost-only network settings if network overrides are NOT allowed
if !self.allow_network_overrides {
config_builder = config_builder
.discovery_addr(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0))
.listener_addr(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0))
.disable_dns_discovery() .disable_dns_discovery()
.disable_nat(); .disable_nat()
} .boot_nodes(boot_nodes())
.set_head(ctx.head())
config_builder = config_builder .with_pow()
.boot_nodes(boot_nodes()) .block_import(Box::new(HlBlockImport::new(handle))),
.set_head(ctx.head()) ))
.with_pow()
.block_import(Box::new(HlBlockImport::new(handle)));
Ok(ctx.build_network_config(config_builder))
} }
} }

View File

@ -3,13 +3,8 @@ use alloy_primitives::Address;
use reth_primitives_traits::{BlockBody as BlockBodyTrait, InMemorySize}; use reth_primitives_traits::{BlockBody as BlockBodyTrait, InMemorySize};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::node::types::{ReadPrecompileCall, ReadPrecompileCalls};
HlHeader, use crate::{HlHeader, node::primitives::TransactionSigned};
node::{
primitives::TransactionSigned,
types::{ReadPrecompileCall, ReadPrecompileCalls},
},
};
/// Block body for HL. It is equivalent to Ethereum [`BlockBody`] but additionally stores sidecars /// Block body for HL. It is equivalent to Ethereum [`BlockBody`] but additionally stores sidecars
/// for blob transactions. /// for blob transactions.
@ -38,11 +33,13 @@ pub type BlockBody = alloy_consensus::BlockBody<TransactionSigned, HlHeader>;
impl InMemorySize for HlBlockBody { impl InMemorySize for HlBlockBody {
fn size(&self) -> usize { fn size(&self) -> usize {
self.inner.size() + self.inner.size()
self.sidecars + self
.sidecars
.as_ref() .as_ref()
.map_or(0, |s| s.capacity() * core::mem::size_of::<BlobTransactionSidecar>()) + .map_or(0, |s| s.capacity() * core::mem::size_of::<BlobTransactionSidecar>())
self.read_precompile_calls + self
.read_precompile_calls
.as_ref() .as_ref()
.map_or(0, |s| s.0.capacity() * core::mem::size_of::<ReadPrecompileCall>()) .map_or(0, |s| s.0.capacity() * core::mem::size_of::<ReadPrecompileCall>())
} }

View File

@ -45,11 +45,7 @@ pub struct HlHeaderExtras {
} }
impl HlHeader { impl HlHeader {
pub(crate) fn from_ethereum_header( pub(crate) fn from_ethereum_header(header: Header, receipts: &[EthereumReceipt], system_tx_count: u64) -> HlHeader {
header: Header,
receipts: &[EthereumReceipt],
system_tx_count: u64,
) -> HlHeader {
let logs_bloom = logs_bloom(receipts.iter().flat_map(|r| &r.logs)); let logs_bloom = logs_bloom(receipts.iter().flat_map(|r| &r.logs));
HlHeader { HlHeader {
inner: header, inner: header,
@ -187,9 +183,8 @@ impl reth_codecs::Compact for HlHeader {
// because Compact trait requires the Bytes field to be placed at the end of the struct. // because Compact trait requires the Bytes field to be placed at the end of the struct.
// Bytes::from_compact just reads all trailing data as the Bytes field. // Bytes::from_compact just reads all trailing data as the Bytes field.
// //
// Hence we need to use other form of serialization, since extra headers are not // Hence we need to use other form of serialization, since extra headers are not Compact-compatible.
// Compact-compatible. We just treat all header fields as rmp-serialized one `Bytes` // We just treat all header fields as rmp-serialized one `Bytes` field.
// field.
let result: Bytes = rmp_serde::to_vec(&self).unwrap().into(); let result: Bytes = rmp_serde::to_vec(&self).unwrap().into();
result.to_compact(buf) result.to_compact(buf)
} }

View File

@ -1,6 +1,6 @@
#![allow(clippy::owned_cow)] #![allow(clippy::owned_cow)]
use super::{HlBlock, HlBlockBody, TransactionSigned}; use super::{HlBlock, HlBlockBody, TransactionSigned};
use crate::{HlHeader, node::types::ReadPrecompileCalls}; use crate::{node::types::ReadPrecompileCalls, HlHeader};
use alloy_consensus::{BlobTransactionSidecar, BlockBody}; use alloy_consensus::{BlobTransactionSidecar, BlockBody};
use alloy_eips::eip4895::Withdrawals; use alloy_eips::eip4895::Withdrawals;
use alloy_primitives::Address; use alloy_primitives::Address;

View File

@ -6,10 +6,7 @@ use serde::{Deserialize, Serialize};
use std::borrow::Cow; use std::borrow::Cow;
use super::{HlBlock, HlBlockBody}; use super::{HlBlock, HlBlockBody};
use crate::{ use crate::{node::{primitives::BlockBody, types::ReadPrecompileCalls}, HlHeader};
HlHeader,
node::{primitives::BlockBody, types::ReadPrecompileCalls},
};
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct HlBlockBodyBincode<'a> { pub struct HlBlockBodyBincode<'a> {

View File

@ -3,15 +3,9 @@ use crate::node::{
storage::tables::{self, SPOT_METADATA_KEY}, storage::tables::{self, SPOT_METADATA_KEY},
types::reth_compat, types::reth_compat,
}; };
use alloy_primitives::Address; use alloy_primitives::{Address, Bytes};
use reth_db::{ use reth_db::{DatabaseEnv, cursor::{DbCursorRO, DbCursorRW}};
DatabaseEnv, use reth_db_api::{Database, transaction::{DbTx, DbTxMut}};
cursor::DbCursorRO,
};
use reth_db_api::{
Database,
transaction::DbTx,
};
use std::{collections::BTreeMap, sync::Arc}; use std::{collections::BTreeMap, sync::Arc};
use tracing::info; use tracing::info;
@ -24,17 +18,11 @@ pub fn load_spot_metadata_cache(db: &Arc<DatabaseEnv>, chain_id: u64) {
}) { }) {
Ok(Ok(data)) => data, Ok(Ok(data)) => data,
Ok(Err(e)) => { Ok(Err(e)) => {
info!( info!("Failed to read spot metadata from database: {}. Will fetch on-demand from API.", e);
"Failed to read spot metadata from database: {}. Will fetch on-demand from API.",
e
);
return; return;
} }
Err(e) => { Err(e) => {
info!( info!("Database view error while loading spot metadata: {}. Will fetch on-demand from API.", e);
"Database view error while loading spot metadata: {}. Will fetch on-demand from API.",
e
);
return; return;
} }
}; };
@ -58,8 +46,10 @@ pub fn load_spot_metadata_cache(db: &Arc<DatabaseEnv>, chain_id: u64) {
}; };
// Convert and initialize cache // Convert and initialize cache
let metadata: BTreeMap<Address, SpotId> = let metadata: BTreeMap<Address, SpotId> = serializable_map
serializable_map.into_iter().map(|(addr, index)| (addr, SpotId { index })).collect(); .into_iter()
.map(|(addr, index)| (addr, SpotId { index }))
.collect();
info!("Loaded spot metadata from database ({} entries)", metadata.len()); info!("Loaded spot metadata from database ({} entries)", metadata.len());
reth_compat::initialize_spot_metadata_cache(metadata); reth_compat::initialize_spot_metadata_cache(metadata);
@ -95,8 +85,21 @@ pub fn init_spot_metadata(
} }
}; };
// Store to database // Serialize and store
reth_compat::store_spot_metadata(&db, &metadata)?; let serializable_map: BTreeMap<Address, u64> =
metadata.iter().map(|(addr, spot)| (*addr, spot.index)).collect();
db.update(|tx| -> Result<(), reth_db::DatabaseError> {
let mut cursor = tx.cursor_write::<tables::SpotMetadata>()?;
cursor.upsert(
SPOT_METADATA_KEY,
&Bytes::from(
rmp_serde::to_vec(&serializable_map)
.expect("Failed to serialize spot metadata"),
),
)?;
Ok(())
})??;
info!("Successfully fetched and stored spot metadata for chain {}", chain_id); info!("Successfully fetched and stored spot metadata for chain {}", chain_id);
Ok(()) Ok(())

View File

@ -1,8 +1,9 @@
//! Copy of reth codebase to preserve serialization compatibility //! Copy of reth codebase to preserve serialization compatibility
use crate::chainspec::TESTNET_CHAIN_ID;
use crate::node::storage::tables::{SPOT_METADATA_KEY, SpotMetadata}; use crate::node::storage::tables::{SPOT_METADATA_KEY, SpotMetadata};
use alloy_consensus::{Header, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy}; use alloy_consensus::{Header, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy};
use alloy_primitives::{Address, BlockHash, Bytes, Signature, TxKind, U256}; use alloy_primitives::{Address, BlockHash, Bytes, Signature, TxKind, U256};
use reth_db::{DatabaseEnv, DatabaseError, cursor::DbCursorRW}; use reth_db::cursor::DbCursorRW;
use reth_db_api::{Database, transaction::DbTxMut}; use reth_db_api::{Database, transaction::DbTxMut};
use reth_primitives::TransactionSigned as RethTxSigned; use reth_primitives::TransactionSigned as RethTxSigned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -84,49 +85,45 @@ pub struct SealedBlock {
pub body: BlockBody, pub body: BlockBody,
} }
static SPOT_EVM_MAP: LazyLock<Arc<RwLock<BTreeMap<Address, SpotId>>>> = static EVM_MAP: LazyLock<Arc<RwLock<BTreeMap<Address, SpotId>>>> =
LazyLock::new(|| Arc::new(RwLock::new(BTreeMap::new()))); LazyLock::new(|| Arc::new(RwLock::new(BTreeMap::new())));
// Optional database handle for persisting on-demand fetches // Optional database handle for persisting on-demand fetches
static DB_HANDLE: LazyLock<Mutex<Option<Arc<DatabaseEnv>>>> = LazyLock::new(|| Mutex::new(None)); static DB_HANDLE: LazyLock<Mutex<Option<Arc<reth_db::DatabaseEnv>>>> =
LazyLock::new(|| Mutex::new(None));
/// Set the database handle for persisting spot metadata /// Set the database handle for persisting spot metadata
pub fn set_spot_metadata_db(db: Arc<DatabaseEnv>) { pub fn set_spot_metadata_db(db: Arc<reth_db::DatabaseEnv>) {
*DB_HANDLE.lock().unwrap() = Some(db); *DB_HANDLE.lock().unwrap() = Some(db);
} }
/// Initialize the spot metadata cache with data loaded from database. /// Initialize the spot metadata cache with data loaded from database.
/// This should be called during node initialization. /// This should be called during node initialization.
pub fn initialize_spot_metadata_cache(metadata: BTreeMap<Address, SpotId>) { pub fn initialize_spot_metadata_cache(metadata: BTreeMap<Address, SpotId>) {
*SPOT_EVM_MAP.write().unwrap() = metadata; *EVM_MAP.write().unwrap() = metadata;
}
/// Helper function to serialize and store spot metadata to database
pub fn store_spot_metadata(
db: &Arc<DatabaseEnv>,
metadata: &BTreeMap<Address, SpotId>,
) -> Result<(), DatabaseError> {
db.update(|tx| {
let mut cursor = tx.cursor_write::<SpotMetadata>()?;
// Serialize to BTreeMap<Address, u64>
let serializable_map: BTreeMap<Address, u64> =
metadata.iter().map(|(addr, spot)| (*addr, spot.index)).collect();
cursor.upsert(
SPOT_METADATA_KEY,
&Bytes::from(
rmp_serde::to_vec(&serializable_map).expect("Failed to serialize spot metadata"),
),
)?;
Ok(())
})?
} }
/// Persist spot metadata to database if handle is available /// Persist spot metadata to database if handle is available
fn persist_spot_metadata_to_db(metadata: &BTreeMap<Address, SpotId>) { fn persist_spot_metadata_to_db(metadata: &BTreeMap<Address, SpotId>) {
if let Some(db) = DB_HANDLE.lock().unwrap().as_ref() { if let Some(db) = DB_HANDLE.lock().unwrap().as_ref() {
match store_spot_metadata(db, metadata) { let result = db.update(|tx| -> Result<(), reth_db::DatabaseError> {
let mut cursor = tx.cursor_write::<SpotMetadata>()?;
// Serialize to BTreeMap<Address, u64>
let serializable_map: BTreeMap<Address, u64> =
metadata.iter().map(|(addr, spot)| (*addr, spot.index)).collect();
cursor.upsert(
SPOT_METADATA_KEY,
&Bytes::from(
rmp_serde::to_vec(&serializable_map)
.expect("Failed to serialize spot metadata"),
),
)?;
Ok(())
});
match result {
Ok(_) => info!("Persisted spot metadata to database"), Ok(_) => info!("Persisted spot metadata to database"),
Err(e) => info!("Failed to persist spot metadata to database: {}", e), Err(e) => info!("Failed to persist spot metadata to database: {}", e),
} }
@ -144,14 +141,14 @@ fn system_tx_to_reth_transaction(transaction: &SystemTx, chain_id: u64) -> TxSig
U256::from(0x1) U256::from(0x1)
} else { } else {
loop { loop {
if let Some(spot) = SPOT_EVM_MAP.read().unwrap().get(&to) { if let Some(spot) = EVM_MAP.read().unwrap().get(&to) {
break spot.to_s(); break spot.to_s();
} }
// Cache miss - fetch from API, update cache, and persist to database // Cache miss - fetch from API, update cache, and persist to database
info!("Contract not found: {to:?} from spot mapping, fetching from API..."); info!("Contract not found: {to:?} from spot mapping, fetching from API...");
let metadata = erc20_contract_to_spot_token(chain_id).unwrap(); let metadata = erc20_contract_to_spot_token(chain_id).unwrap();
*SPOT_EVM_MAP.write().unwrap() = metadata.clone(); *EVM_MAP.write().unwrap() = metadata.clone();
persist_spot_metadata_to_db(&metadata); persist_spot_metadata_to_db(&metadata);
} }
}; };
@ -168,8 +165,11 @@ impl SealedBlock {
receipts: Vec<LegacyReceipt>, receipts: Vec<LegacyReceipt>,
chain_id: u64, chain_id: u64,
) -> HlBlock { ) -> HlBlock {
// NOTE: These types of transactions are tracked at #97. // NOTE: Filter out system transactions that may be rejected by the EVM (tracked by #97,
system_txs.retain(|tx| tx.receipt.is_some()); // testnet only).
if chain_id == TESTNET_CHAIN_ID {
system_txs = system_txs.into_iter().filter(|tx| tx.receipt.is_some()).collect();
}
let mut merged_txs = vec![]; let mut merged_txs = vec![];
merged_txs.extend(system_txs.iter().map(|tx| system_tx_to_reth_transaction(tx, chain_id))); merged_txs.extend(system_txs.iter().map(|tx| system_tx_to_reth_transaction(tx, chain_id)));

View File

@ -82,8 +82,8 @@ impl BlockPoller {
.ok_or(eyre::eyre!("Failed to find latest block number"))?; .ok_or(eyre::eyre!("Failed to find latest block number"))?;
loop { loop {
if let Some(debug_cutoff_height) = debug_cutoff_height && if let Some(debug_cutoff_height) = debug_cutoff_height
next_block_number > debug_cutoff_height && next_block_number > debug_cutoff_height
{ {
next_block_number = debug_cutoff_height; next_block_number = debug_cutoff_height;
} }