diff --git a/crates/blockchain/blockchain.rs b/crates/blockchain/blockchain.rs index 593ca6fb5be..9fcc40be120 100644 --- a/crates/blockchain/blockchain.rs +++ b/crates/blockchain/blockchain.rs @@ -42,7 +42,7 @@ use mempool::Mempool; use payload::PayloadOrTask; use rustc_hash::FxHashMap; use std::collections::hash_map::Entry; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::sync::{ Arc, Mutex, RwLock, atomic::{AtomicBool, AtomicUsize, Ordering}, @@ -727,6 +727,7 @@ impl Blockchain { let mut blockhash_opcode_references = HashMap::new(); let mut codes = Vec::new(); + let mut seen_code_hashes = BTreeSet::new(); for (i, block) in blocks.iter().enumerate() { let parent_hash = block.header.parent_hash; @@ -844,6 +845,11 @@ impl Blockchain { })? .iter() { + // Deduplicate bytecodes by their code hash to avoid redundant allocations + if !seen_code_hashes.insert(*code_hash) { + continue; + } + let code = self .storage .get_account_code(*code_hash) @@ -876,8 +882,7 @@ impl Blockchain { ChainError::WitnessGeneration("Failed to lock storage trie witness".to_string()) })?; let witness = std::mem::take(&mut *witness); - let witness = witness.into_values().collect::>(); - used_trie_nodes.extend_from_slice(&witness); + used_trie_nodes.extend(witness.into_values()); touched_account_storage_slots.entry(address).or_default(); } @@ -905,9 +910,7 @@ impl Blockchain { current_trie_witness = new_state_trie_witness; } - used_trie_nodes.extend_from_slice(&Vec::from_iter( - accumulated_state_trie_witness.into_values(), - )); + used_trie_nodes.extend(accumulated_state_trie_witness.into_values()); // If the witness is empty at least try to store the root if used_trie_nodes.is_empty()