From 1efdedb06baf5e764e6da12109eef41fbdaa9de3 Mon Sep 17 00:00:00 2001 From: Haardik H Date: Thu, 30 Oct 2025 14:13:06 -0400 Subject: [PATCH 1/4] perf --- crates/flashblocks-rpc/src/state.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/flashblocks-rpc/src/state.rs b/crates/flashblocks-rpc/src/state.rs index 5aa6b4f8..ac19ae41 100644 --- a/crates/flashblocks-rpc/src/state.rs +++ b/crates/flashblocks-rpc/src/state.rs @@ -10,7 +10,7 @@ use alloy_primitives::map::B256HashMap; use alloy_primitives::{Address, BlockNumber, Bytes, Sealable, B256, U256}; use alloy_rpc_types::{TransactionTrait, Withdrawal}; use alloy_rpc_types_engine::{ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3}; -use alloy_rpc_types_eth::state::{AccountOverride, StateOverride, StateOverridesBuilder}; +use alloy_rpc_types_eth::state::{AccountOverride, StateOverride}; use alloy_rpc_types_eth::{Filter, Log}; use arc_swap::{ArcSwapOption, Guard}; use eyre::eyre; @@ -618,8 +618,6 @@ where match evm.transact(recovered_transaction) { Ok(ResultAndState { state, .. }) => { for (addr, acc) in &state { - let mut state_cache_builder = - StateOverridesBuilder::new(state_overrides.clone()); let curr_state_diff = B256HashMap::::from_iter(acc.storage.iter().map( |(&key, slot)| (key.into(), slot.present_value.into()), @@ -642,9 +640,8 @@ where state_diff: Some(state_diff), move_precompile_to: None, }; - state_cache_builder = - state_cache_builder.append(*addr, acc_override); - state_overrides = state_cache_builder.build(); + + state_overrides.insert(*addr, acc_override); } pending_blocks_builder .with_transaction_state(transaction.tx_hash(), state.clone()); From 28912c5044ef58f206ced725d7924b838841f5b7 Mon Sep 17 00:00:00 2001 From: Haardik H Date: Thu, 30 Oct 2025 14:51:39 -0400 Subject: [PATCH 2/4] less clones --- crates/flashblocks-rpc/src/state.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/flashblocks-rpc/src/state.rs b/crates/flashblocks-rpc/src/state.rs index ac19ae41..40bd9c48 100644 --- a/crates/flashblocks-rpc/src/state.rs +++ b/crates/flashblocks-rpc/src/state.rs @@ -237,13 +237,13 @@ where block_number = flashblock.metadata.block_number, flashblock_index = flashblock.index ); - match self.process_flashblock(prev_pending_blocks, &flashblock) { + match self.process_flashblock(prev_pending_blocks, flashblock) { Ok(new_pending_blocks) => { if new_pending_blocks.is_some() { _ = self.sender.send(new_pending_blocks.clone().unwrap()) } - self.pending_blocks.swap(new_pending_blocks.clone()); + self.pending_blocks.swap(new_pending_blocks); self.metrics .block_processing_duration .record(start_time.elapsed()); @@ -327,15 +327,15 @@ where fn process_flashblock( &self, prev_pending_blocks: Option>, - flashblock: &Flashblock, + flashblock: Flashblock, ) -> eyre::Result>> { match &prev_pending_blocks { Some(pending_blocks) => { - if self.is_next_flashblock(pending_blocks, flashblock) { + if self.is_next_flashblock(pending_blocks, &flashblock) { // We have received the next flashblock for the current block // or the first flashblock for the next block let mut flashblocks = pending_blocks.get_flashblocks(); - flashblocks.push(flashblock.clone()); + flashblocks.push(flashblock); self.build_pending_state(prev_pending_blocks, &flashblocks) } else if pending_blocks.latest_block_number() != flashblock.metadata.block_number { // We have received a non-zero flashblock for a new block @@ -354,7 +354,7 @@ where curr_block = %pending_blocks.latest_block_number(), flashblock_index = %flashblock.index, ); - Ok(prev_pending_blocks.clone()) + Ok(prev_pending_blocks) } else { // We have received a non-sequential flashblock for the current block self.metrics.unexpected_block_order.increment(1); @@ -370,7 +370,7 @@ where } None => { if flashblock.index == 0 { - self.build_pending_state(None, &vec![flashblock.clone()]) + self.build_pending_state(None, &vec![flashblock]) } else { info!(message = "waiting for first Flashblock"); Ok(None) @@ -385,12 +385,12 @@ where flashblocks: &Vec, ) -> eyre::Result>> { // BTreeMap guarantees ascending order of keys while iterating - let mut flashblocks_per_block = BTreeMap::>::new(); + let mut flashblocks_per_block = BTreeMap::>::new(); for flashblock in flashblocks { flashblocks_per_block .entry(flashblock.metadata.block_number) .or_default() - .push(flashblock.clone()); + .push(flashblock); } let earliest_block_number = flashblocks_per_block.keys().min().unwrap(); @@ -463,7 +463,12 @@ where acc }); - pending_blocks_builder.with_flashblocks(flashblocks.clone()); + pending_blocks_builder.with_flashblocks( + flashblocks + .iter() + .map(|&x| x.clone()) + .collect::>(), + ); let execution_payload: ExecutionPayloadV3 = ExecutionPayloadV3 { blob_gas_used: 0, From dae206445db8b07f4372b95436314ede064afa74 Mon Sep 17 00:00:00 2001 From: Danyal Prout Date: Thu, 30 Oct 2025 13:51:57 -0500 Subject: [PATCH 3/4] remove clones / map lookups (#156) --- crates/flashblocks-rpc/src/state.rs | 38 +++++++++-------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/crates/flashblocks-rpc/src/state.rs b/crates/flashblocks-rpc/src/state.rs index 40bd9c48..7ef1a972 100644 --- a/crates/flashblocks-rpc/src/state.rs +++ b/crates/flashblocks-rpc/src/state.rs @@ -6,11 +6,10 @@ use alloy_consensus::transaction::{Recovered, SignerRecoverable, TransactionMeta use alloy_consensus::{Header, TxReceipt}; use alloy_eips::BlockNumberOrTag; use alloy_primitives::map::foldhash::HashMap; -use alloy_primitives::map::B256HashMap; use alloy_primitives::{Address, BlockNumber, Bytes, Sealable, B256, U256}; use alloy_rpc_types::{TransactionTrait, Withdrawal}; use alloy_rpc_types_engine::{ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3}; -use alloy_rpc_types_eth::state::{AccountOverride, StateOverride}; +use alloy_rpc_types_eth::state::{StateOverride}; use alloy_rpc_types_eth::{Filter, Log}; use arc_swap::{ArcSwapOption, Guard}; use eyre::eyre; @@ -623,30 +622,17 @@ where match evm.transact(recovered_transaction) { Ok(ResultAndState { state, .. }) => { for (addr, acc) in &state { - let curr_state_diff = - B256HashMap::::from_iter(acc.storage.iter().map( - |(&key, slot)| (key.into(), slot.present_value.into()), - )); - - let mut state_diff = state_overrides - .get(addr) - .cloned() - .unwrap_or_default() - .state_diff - .unwrap_or_default(); - - state_diff.extend(curr_state_diff); - - let acc_override = AccountOverride { - balance: Some(acc.info.balance), - nonce: Some(acc.info.nonce), - code: acc.info.code.clone().map(|code| code.bytes()), - state: None, - state_diff: Some(state_diff), - move_precompile_to: None, - }; - - state_overrides.insert(*addr, acc_override); + let existing_override = state_overrides.entry(*addr).or_insert(Default::default()); + existing_override.balance = Some(acc.info.balance); + existing_override.nonce = Some(acc.info.nonce); + existing_override.code = acc.info.code.clone().map(|code| code.bytes()); + + let existing = existing_override.state_diff.get_or_insert(Default::default()); + let changed_slots = acc.storage.iter().map( + |(&key, slot)| (B256::from(key), B256::from(slot.present_value)), + ); + + existing.extend(changed_slots); } pending_blocks_builder .with_transaction_state(transaction.tx_hash(), state.clone()); From fef73768e5cdefbb44e1a0b4614d03e2feb6d727 Mon Sep 17 00:00:00 2001 From: Haardik H Date: Thu, 30 Oct 2025 14:55:01 -0400 Subject: [PATCH 4/4] lint --- crates/flashblocks-rpc/src/state.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/flashblocks-rpc/src/state.rs b/crates/flashblocks-rpc/src/state.rs index 7ef1a972..fd060ccb 100644 --- a/crates/flashblocks-rpc/src/state.rs +++ b/crates/flashblocks-rpc/src/state.rs @@ -9,7 +9,7 @@ use alloy_primitives::map::foldhash::HashMap; use alloy_primitives::{Address, BlockNumber, Bytes, Sealable, B256, U256}; use alloy_rpc_types::{TransactionTrait, Withdrawal}; use alloy_rpc_types_engine::{ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3}; -use alloy_rpc_types_eth::state::{StateOverride}; +use alloy_rpc_types_eth::state::StateOverride; use alloy_rpc_types_eth::{Filter, Log}; use arc_swap::{ArcSwapOption, Guard}; use eyre::eyre; @@ -622,15 +622,19 @@ where match evm.transact(recovered_transaction) { Ok(ResultAndState { state, .. }) => { for (addr, acc) in &state { - let existing_override = state_overrides.entry(*addr).or_insert(Default::default()); + let existing_override = + state_overrides.entry(*addr).or_insert(Default::default()); existing_override.balance = Some(acc.info.balance); existing_override.nonce = Some(acc.info.nonce); - existing_override.code = acc.info.code.clone().map(|code| code.bytes()); - - let existing = existing_override.state_diff.get_or_insert(Default::default()); - let changed_slots = acc.storage.iter().map( - |(&key, slot)| (B256::from(key), B256::from(slot.present_value)), - ); + existing_override.code = + acc.info.code.clone().map(|code| code.bytes()); + + let existing = existing_override + .state_diff + .get_or_insert(Default::default()); + let changed_slots = acc.storage.iter().map(|(&key, slot)| { + (B256::from(key), B256::from(slot.present_value)) + }); existing.extend(changed_slots); }