From e1c2ab77ed8c0efdea36eb302ebdc4f51a791f2d Mon Sep 17 00:00:00 2001 From: Dickson Date: Tue, 1 Sep 2026 20:26:55 +0000 Subject: [PATCH] trie-db: preserve root when dropping uncommitted deletion --- trie-db/src/triedbmut.rs | 6 +++-- trie-db/test/src/triedbmut.rs | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/trie-db/src/triedbmut.rs b/trie-db/src/triedbmut.rs index ba35aed0..bad7d9ea 100644 --- a/trie-db/src/triedbmut.rs +++ b/trie-db/src/triedbmut.rs @@ -1839,7 +1839,10 @@ where } let handle = match self.root_handle() { - NodeHandle::Hash(_) => return, // no changes necessary. + NodeHandle::Hash(hash) => { + *self.root = hash; + return + }, NodeHandle::InMemory(h) => h, }; @@ -2112,7 +2115,6 @@ where #[cfg(feature = "std")] trace!(target: "trie", "remove: obliterated trie"); self.root_handle = NodeHandle::Hash(L::Codec::hashed_null_node()); - *self.root = L::Codec::hashed_null_node(); }, } diff --git a/trie-db/test/src/triedbmut.rs b/trie-db/test/src/triedbmut.rs index d1ff8449..a5cc5c66 100644 --- a/trie-db/test/src/triedbmut.rs +++ b/trie-db/test/src/triedbmut.rs @@ -930,6 +930,48 @@ fn test_commit_on_drop_disabled_internal() { ); } +test_layouts!( + test_commit_on_drop_disabled_after_removing_last_key, + test_commit_on_drop_disabled_after_removing_last_key_internal +); +fn test_commit_on_drop_disabled_after_removing_last_key_internal() { + let (mut memdb, mut root) = prepare_test_trie::(); + let root_before = root.clone(); + let db_key_count_before = memdb.keys().len(); + + { + let mut trie = TrieDBMutBuilder::::from_existing(&mut memdb, &mut root) + .disable_commit_on_drop() + .build(); + trie.remove(b"existing_key").unwrap(); + assert!(trie.is_empty()); + } + + assert_eq!(root, root_before, "Root should not change after drop without commit"); + assert_eq!( + memdb.keys().len(), + db_key_count_before, + "Database should not change after drop without commit" + ); + + { + let trie = TrieDBBuilder::::new(&memdb, &root).build(); + assert_eq!(trie.get(b"existing_key").unwrap(), Some(b"existing_value".to_vec())); + } + + { + let mut trie = TrieDBMutBuilder::::from_existing(&mut memdb, &mut root) + .disable_commit_on_drop() + .build(); + trie.remove(b"existing_key").unwrap(); + trie.commit(); + } + assert_eq!(root, reference_hashed_null_node::()); + + let trie = TrieDBBuilder::::new(&memdb, &root).build(); + assert_eq!(trie.get(b"existing_key").unwrap(), None); +} + test_layouts!(test_commit_on_drop_enabled, test_commit_on_drop_enabled_internal); fn test_commit_on_drop_enabled_internal() { let (mut memdb, mut root) = prepare_test_trie::();