diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 8bf813d1f24..dbfc3be6e9a 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -306,6 +306,8 @@ impl DatabaseProvider DatabaseProvider StateWriter ) -> ProviderResult<()> { // Write storage changes tracing::trace!("Writing storage changes"); - let mut storages_cursor = self.tx_ref().cursor_dup_write::()?; + let mut storages_cursor = self.tx_ref().cursor_dup_read::()?; let mut storage_changeset_cursor = self.tx_ref().cursor_dup_write::()?; for (block_index, mut storage_changes) in reverts.storage.into_iter().enumerate() { diff --git a/crates/trie/common/src/utils.rs b/crates/trie/common/src/utils.rs index 5a2234fe26b..8cc94b3c031 100644 --- a/crates/trie/common/src/utils.rs +++ b/crates/trie/common/src/utils.rs @@ -1,14 +1,15 @@ use alloc::vec::Vec; +use itertools::Itertools; /// Helper function to extend a sorted vector with another sorted vector. /// Values from `other` take precedence for duplicate keys. /// -/// This function efficiently merges two sorted vectors by: -/// 1. Iterating through the target vector with mutable references -/// 2. Using a peekable iterator for the other vector -/// 3. For each target item, processing other items that come before or equal to it -/// 4. Collecting items from other that need to be inserted -/// 5. Appending and re-sorting only if new items were added +/// **Both `target` and `other` MUST be sorted by key** for this function to work correctly. +/// If not, the result will be incorrect and may not maintain sorted order. +/// +/// This function efficiently merges two sorted vectors using `itertools::merge_join_by`: +/// 1. Merges in one pass (O(n+m)) by comparing keys +/// 2. For duplicate keys, `other` values take precedence pub(crate) fn extend_sorted_vec(target: &mut Vec<(K, V)>, other: &[(K, V)]) where K: Clone + Ord, @@ -18,36 +19,16 @@ where return; } - let mut other_iter = other.iter().peekable(); - let mut to_insert = Vec::new(); - - // Iterate through target and update/collect items from other - for target_item in target.iter_mut() { - while let Some(other_item) = other_iter.peek() { - use core::cmp::Ordering; - match other_item.0.cmp(&target_item.0) { - Ordering::Less => { - // Other item comes before current target item, collect it - to_insert.push(other_iter.next().unwrap().clone()); - } - Ordering::Equal => { - // Same key, update target with other's value - target_item.1 = other_iter.next().unwrap().1.clone(); - break; - } - Ordering::Greater => { - // Other item comes after current target item, keep target unchanged - break; - } + *target = target + .iter() + .merge_join_by(other.iter(), |(k1, _), (k2, _)| k1.cmp(k2)) + .map(|entry| { + // Extract the item: for duplicates, use other's value + match entry { + itertools::EitherOrBoth::Left(item) | + itertools::EitherOrBoth::Right(item) | + itertools::EitherOrBoth::Both(_, item) => item.clone(), } - } - } - - // Append collected new items, as well as any remaining from `other` which are necessarily also - // new, and sort if needed - if !to_insert.is_empty() || other_iter.peek().is_some() { - target.extend(to_insert); - target.extend(other_iter.cloned()); - target.sort_unstable_by(|a, b| a.0.cmp(&b.0)); - } + }) + .collect(); }