]> Untitled Git - bdk/commitdiff
fix(chain): simplify `Append::append` impl for `keychain::ChangeSet`
author志宇 <hello@evanlinjin.me>
Sat, 4 May 2024 15:37:42 +0000 (23:37 +0800)
committerDaniela Brozzoni <danielabrozzoni@protonmail.com>
Wed, 8 May 2024 13:49:45 +0000 (15:49 +0200)
We only need to loop though entries of `other`. The logic before was
wasteful because we were also looping though all entries of `self` even
if we do not need to modify the `self` entry.

crates/chain/src/keychain/txout_index.rs

index e0c132dc26619e427e903b5a7d8f413ad84700e5..aa0e86ef2a84d859c9d9ba23c75b01d4cdc7e8af 100644 (file)
@@ -49,23 +49,26 @@ impl<K: Ord> Append for ChangeSet<K> {
     ///
     /// For each `last_revealed` in the given [`ChangeSet`]:
     /// If the keychain already exists, increase the index when the other's index > self's index.
-    fn append(&mut self, mut other: Self) {
-        for (keychain, descriptor) in &mut self.keychains_added {
-            if let Some(other_descriptor) = other.keychains_added.remove(keychain) {
-                *descriptor = other_descriptor;
-            }
-        }
-
-        for (descriptor_id, index) in &mut self.last_revealed {
-            if let Some(other_index) = other.last_revealed.remove(descriptor_id) {
-                *index = other_index.max(*index);
-            }
-        }
-
+    fn append(&mut self, other: Self) {
         // We use `extend` instead of `BTreeMap::append` due to performance issues with `append`.
         // Refer to https://github.com/rust-lang/rust/issues/34666#issuecomment-675658420
         self.keychains_added.extend(other.keychains_added);
-        self.last_revealed.extend(other.last_revealed);
+
+        // for `last_revealed`, entries of `other` will take precedence ONLY if it is greater than
+        // what was originally in `self`.
+        for (desc_id, index) in other.last_revealed {
+            use crate::collections::btree_map::Entry;
+            match self.last_revealed.entry(desc_id) {
+                Entry::Vacant(entry) => {
+                    entry.insert(index);
+                }
+                Entry::Occupied(mut entry) => {
+                    if *entry.get() < index {
+                        entry.insert(index);
+                    }
+                }
+            }
+        }
     }
 
     /// Returns whether the changeset are empty.