From df078b42b78dbee15d87a242277e0a6b5a7083bd Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 2 Oct 2025 10:08:08 +0500 Subject: [PATCH 1/5] fix decode compact prefix db - partial prefix for attached value was not appended - support for child trie root prefix --- trie-db/src/lib.rs | 2 +- trie-db/src/trie_codec.rs | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/trie-db/src/lib.rs b/trie-db/src/lib.rs index 2c091eaa5..aa435ba6b 100644 --- a/trie-db/src/lib.rs +++ b/trie-db/src/lib.rs @@ -81,7 +81,7 @@ pub use crate::{ iter_build::{trie_visit, ProcessEncodedNode, TrieBuilder, TrieRoot, TrieRootUnhashed}, iterator::{TrieDBNodeIterator, TrieDBRawIterator}, node_codec::{NodeCodec, Partial}, - trie_codec::{decode_compact, decode_compact_from_iter, encode_compact}, + trie_codec::{decode_compact, decode_compact_from_iter, decode_compact_from_iter_with_prefix, encode_compact}, }; pub use hash_db::{HashDB, HashDBRef, Hasher}; diff --git a/trie-db/src/trie_codec.rs b/trie-db/src/trie_codec.rs index 22faf4487..11171cb52 100644 --- a/trie-db/src/trie_codec.rs +++ b/trie-db/src/trie_codec.rs @@ -29,7 +29,7 @@ use crate::{ nibble_ops::NIBBLE_LENGTH, node::{Node, NodeHandle, NodeHandlePlan, NodePlan, OwnedNode, ValuePlan}, rstd::{boxed::Box, convert::TryInto, marker::PhantomData, result, sync::Arc, vec, vec::Vec}, - CError, ChildReference, DBValue, NibbleVec, NodeCodec, Result, TrieDB, TrieDBRawIterator, + CError, ChildReference, DBValue, NibbleSlice, NibbleVec, NodeCodec, Result, TrieDB, TrieDBRawIterator, TrieError, TrieHash, TrieLayout, }; use hash_db::{HashDB, Prefix}; @@ -459,6 +459,21 @@ pub fn decode_compact_from_iter<'a, L, DB, I>( db: &mut DB, encoded: I, ) -> Result<(TrieHash, usize), TrieHash, CError> +where + L: TrieLayout, + DB: HashDB, + I: IntoIterator, +{ + decode_compact_from_iter_with_prefix::(db, encoded, &[]) +} + +/// Variant of 'decode_compact' that accept an iterator of encoded nodes as input, +/// and root prefix. +pub fn decode_compact_from_iter_with_prefix<'a, L, DB, I>( + db: &mut DB, + encoded: I, + root_prefix: &[u8], +) -> Result<(TrieHash, usize), TrieHash, CError> where L: TrieLayout, DB: HashDB, @@ -469,7 +484,7 @@ where let mut stack: Vec> = Vec::new(); // The prefix of the next item to be read from the slice of encoded items. - let mut prefix = NibbleVec::new(); + let mut prefix = NibbleVec::from(NibbleSlice::new(root_prefix)); let mut iter = encoded.into_iter().enumerate(); while let Some((i, encoded_node)) = iter.next() { @@ -516,7 +531,18 @@ where let hash = last_entry .attached_value .as_ref() - .map(|value| db.insert(prefix.as_prefix(), value)); + .map(|value| { + let partial_prefix_len = match &last_entry.node { + Node::Leaf(partial, _) | Node::NibbledBranch(partial, _, _) => { + prefix.append_partial(partial.right()); + partial.len() + }, + _ => 0, + }; + let hash = db.insert(prefix.as_prefix(), value); + prefix.drop_lasts(partial_prefix_len); + hash + }); let node_data = last_entry.encode_node(hash.as_ref().map(|h| h.as_ref())); let node_hash = db.insert(prefix.as_prefix(), node_data.as_ref()); From cd830e9b38617de53a57619a78e00182913f3530 Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 2 Oct 2025 21:34:43 +0500 Subject: [PATCH 2/5] regression test - decode compact proof to prefixed db, trie read failed --- trie-db/test/src/trie_codec.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/trie-db/test/src/trie_codec.rs b/trie-db/test/src/trie_codec.rs index 17b52cb53..2581c025f 100644 --- a/trie-db/test/src/trie_codec.rs +++ b/trie-db/test/src/trie_codec.rs @@ -25,6 +25,12 @@ type MemoryDB = memory_db::MemoryDB< DBValue, >; +type PrefixedMemoryDB = memory_db::MemoryDB< + ::Hash, + memory_db::PrefixedKey<::Hash>, + DBValue, +>; + fn test_encode_compact( entries: Vec<(&'static [u8], &'static [u8])>, keys: Vec<&'static [u8]>, @@ -76,7 +82,7 @@ fn test_decode_compact( expected_used: usize, ) { // Reconstruct the partial DB from the compact encoding. - let mut db = MemoryDB::::default(); + let mut db = PrefixedMemoryDB::::default(); let (root, used) = decode_compact::(&mut db, encoded).unwrap(); assert_eq!(root, expected_root); assert_eq!(used, expected_used); From 1b973172c233fa7a092f54acfb7de7015582e758 Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 2 Oct 2025 22:36:30 +0500 Subject: [PATCH 3/5] split test - test both MemoryDB and PrefixedMemoryDB --- trie-db/test/src/trie_codec.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/trie-db/test/src/trie_codec.rs b/trie-db/test/src/trie_codec.rs index 2581c025f..20bf3ec29 100644 --- a/trie-db/test/src/trie_codec.rs +++ b/trie-db/test/src/trie_codec.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; +use hash_db::{HashDB, HashDBRef, Hasher, EMPTY_PREFIX}; use reference_trie::{test_layouts, ExtensionLayout}; use trie_db::{ decode_compact, encode_compact, DBValue, NodeCodec, Recorder, Trie, TrieDBBuilder, @@ -76,13 +76,13 @@ fn test_encode_compact( } fn test_decode_compact( + mut db: impl HashDB + HashDBRef, encoded: &[Vec], - items: Vec<(&'static [u8], Option)>, + items: &[(&'static [u8], Option)], expected_root: ::Out, expected_used: usize, ) { // Reconstruct the partial DB from the compact encoding. - let mut db = PrefixedMemoryDB::::default(); let (root, used) = decode_compact::(&mut db, encoded).unwrap(); assert_eq!(root, expected_root); assert_eq!(used, expected_used); @@ -90,7 +90,7 @@ fn test_decode_compact( // Check that lookups for all items succeed. let trie = >::new(&db, &root).build(); for (key, expected_value) in items { - assert_eq!(trie.get(key).unwrap(), expected_value); + assert_eq!(&trie.get(key).unwrap(), expected_value); } } @@ -121,7 +121,8 @@ fn trie_compact_encoding_works_internal() { ); encoded.push(Vec::new()); // Add an extra item to ensure it is not read. - test_decode_compact::(&encoded, items, root, encoded.len() - 1); + test_decode_compact::(MemoryDB::::default(), &encoded, &items, root, encoded.len() - 1); + test_decode_compact::(PrefixedMemoryDB::::default(), &encoded, &items, root, encoded.len() - 1); } test_layouts!( From 60644059cae7d8445661f5fe47036c8218ce66ca Mon Sep 17 00:00:00 2001 From: turuslan Date: Tue, 14 Oct 2025 09:01:12 +0500 Subject: [PATCH 4/5] remove decode_compact_from_iter_with_prefix use KeySpacedDBMut wrapper --- trie-db/src/lib.rs | 2 +- trie-db/src/trie_codec.rs | 19 ++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/trie-db/src/lib.rs b/trie-db/src/lib.rs index aa435ba6b..2c091eaa5 100644 --- a/trie-db/src/lib.rs +++ b/trie-db/src/lib.rs @@ -81,7 +81,7 @@ pub use crate::{ iter_build::{trie_visit, ProcessEncodedNode, TrieBuilder, TrieRoot, TrieRootUnhashed}, iterator::{TrieDBNodeIterator, TrieDBRawIterator}, node_codec::{NodeCodec, Partial}, - trie_codec::{decode_compact, decode_compact_from_iter, decode_compact_from_iter_with_prefix, encode_compact}, + trie_codec::{decode_compact, decode_compact_from_iter, encode_compact}, }; pub use hash_db::{HashDB, HashDBRef, Hasher}; diff --git a/trie-db/src/trie_codec.rs b/trie-db/src/trie_codec.rs index 11171cb52..e41d1976b 100644 --- a/trie-db/src/trie_codec.rs +++ b/trie-db/src/trie_codec.rs @@ -29,7 +29,7 @@ use crate::{ nibble_ops::NIBBLE_LENGTH, node::{Node, NodeHandle, NodeHandlePlan, NodePlan, OwnedNode, ValuePlan}, rstd::{boxed::Box, convert::TryInto, marker::PhantomData, result, sync::Arc, vec, vec::Vec}, - CError, ChildReference, DBValue, NibbleSlice, NibbleVec, NodeCodec, Result, TrieDB, TrieDBRawIterator, + CError, ChildReference, DBValue, NibbleVec, NodeCodec, Result, TrieDB, TrieDBRawIterator, TrieError, TrieHash, TrieLayout, }; use hash_db::{HashDB, Prefix}; @@ -459,21 +459,6 @@ pub fn decode_compact_from_iter<'a, L, DB, I>( db: &mut DB, encoded: I, ) -> Result<(TrieHash, usize), TrieHash, CError> -where - L: TrieLayout, - DB: HashDB, - I: IntoIterator, -{ - decode_compact_from_iter_with_prefix::(db, encoded, &[]) -} - -/// Variant of 'decode_compact' that accept an iterator of encoded nodes as input, -/// and root prefix. -pub fn decode_compact_from_iter_with_prefix<'a, L, DB, I>( - db: &mut DB, - encoded: I, - root_prefix: &[u8], -) -> Result<(TrieHash, usize), TrieHash, CError> where L: TrieLayout, DB: HashDB, @@ -484,7 +469,7 @@ where let mut stack: Vec> = Vec::new(); // The prefix of the next item to be read from the slice of encoded items. - let mut prefix = NibbleVec::from(NibbleSlice::new(root_prefix)); + let mut prefix = NibbleVec::new(); let mut iter = encoded.into_iter().enumerate(); while let Some((i, encoded_node)) = iter.next() { From 5d3b63a9a4ee7e5c3366d8399a05fabfb22d4dcc Mon Sep 17 00:00:00 2001 From: turuslan Date: Tue, 14 Oct 2025 12:44:54 +0500 Subject: [PATCH 5/5] ci rustfmt --- trie-db/src/trie_codec.rs | 27 ++++++++++++--------------- trie-db/test/src/trie_codec.rs | 8 +++++++- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/trie-db/src/trie_codec.rs b/trie-db/src/trie_codec.rs index e41d1976b..da7af4ed9 100644 --- a/trie-db/src/trie_codec.rs +++ b/trie-db/src/trie_codec.rs @@ -513,21 +513,18 @@ where // Since `advance_child_index` returned true, the preconditions for `encode_node` are // satisfied. - let hash = last_entry - .attached_value - .as_ref() - .map(|value| { - let partial_prefix_len = match &last_entry.node { - Node::Leaf(partial, _) | Node::NibbledBranch(partial, _, _) => { - prefix.append_partial(partial.right()); - partial.len() - }, - _ => 0, - }; - let hash = db.insert(prefix.as_prefix(), value); - prefix.drop_lasts(partial_prefix_len); - hash - }); + let hash = last_entry.attached_value.as_ref().map(|value| { + let partial_prefix_len = match &last_entry.node { + Node::Leaf(partial, _) | Node::NibbledBranch(partial, _, _) => { + prefix.append_partial(partial.right()); + partial.len() + }, + _ => 0, + }; + let hash = db.insert(prefix.as_prefix(), value); + prefix.drop_lasts(partial_prefix_len); + hash + }); let node_data = last_entry.encode_node(hash.as_ref().map(|h| h.as_ref())); let node_hash = db.insert(prefix.as_prefix(), node_data.as_ref()); diff --git a/trie-db/test/src/trie_codec.rs b/trie-db/test/src/trie_codec.rs index 20bf3ec29..cd77032ea 100644 --- a/trie-db/test/src/trie_codec.rs +++ b/trie-db/test/src/trie_codec.rs @@ -122,7 +122,13 @@ fn trie_compact_encoding_works_internal() { encoded.push(Vec::new()); // Add an extra item to ensure it is not read. test_decode_compact::(MemoryDB::::default(), &encoded, &items, root, encoded.len() - 1); - test_decode_compact::(PrefixedMemoryDB::::default(), &encoded, &items, root, encoded.len() - 1); + test_decode_compact::( + PrefixedMemoryDB::::default(), + &encoded, + &items, + root, + encoded.len() - 1, + ); } test_layouts!(