trie-db: Fetch the closest merkle value#199
Conversation
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
trie-db/test/src/triedb.rs
Outdated
| } | ||
|
|
||
| #[test] | ||
| fn test_merkle_value() { |
There was a problem hiding this comment.
The test should also check that the functions works correctly for keys that aren't acuatlly in the tree.
E.g. for a tree with nodes ["AAA"] it should return a closest descendant for the key "AA" but not for "AB". For the tree with nodes ["AAAA", "AABA] closes descendant for the key "A" should be the branch node, etc.
Also there's no need to make changes to the test trie after it is created really.
There was a problem hiding this comment.
Also, you don't need to
Argh, the suspense :D
|
After reading the spec more carefully, I think the logic here requires some changes. We need to return the descendant of the provided key, not just the lower bound. Basically this means traversing the tree as usual, but for Leaf, Extension and NibbledBranch nodes if you run out of key, just check if the current node key slice extends the remainder. if slice.starts_with(&partial) {
return Ok(Some(hash)))
else
return Ok(None)
} |
Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>
Co-authored-by: Arkadiy Paronyan <arkady.paronyan@gmail.com>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
cheme
left a comment
There was a problem hiding this comment.
Looks good.
Worth remembering that if at some point this get used in runtime (especially by a host function), not simply rpc, it would be worth fuzzing a bit.
bkchr
left a comment
There was a problem hiding this comment.
Left mainly some nitpicks. However, the return value is wrong. The merkle value is either the node data or the hash, depending on if this is an inline node or not.
trie-db/src/lookup.rs
Outdated
| let mut node = if let Some(cache) = &mut cache { | ||
| let node = cache.get_or_insert_node(hash, &mut || get_owned_node(depth))?; | ||
|
|
||
| self.record(|| TrieAccess::NodeOwned { hash, node_owned: node }); | ||
|
|
||
| node | ||
| } else { | ||
| _owned_node = get_owned_node(depth)?; | ||
|
|
||
| self.record(|| TrieAccess::EncodedNode { | ||
| hash, | ||
| encoded_node: node_data.as_slice().into(), | ||
| }); | ||
|
|
||
| &_owned_node | ||
| }; |
There was a problem hiding this comment.
Now we always need to create an owned node, which is a little bit shitty. But fine for now I think.
trie-db/src/lookup.rs
Outdated
| mut self, | ||
| nibble_key: NibbleSlice, | ||
| full_key: &[u8], | ||
| ) -> Result<Option<TrieHash<L>>, TrieHash<L>, CError<L>> { |
There was a problem hiding this comment.
The return type is wrong.
enum MerkleValue {
/// Is returned if `v.len() < MAX_INLINE_VALUE`.
Node(Vec<u8>),
Hash(H),
}
There was a problem hiding this comment.
I did propose to use hash for inline node (generally I would prefer if inline node is something users don't need to be aware off). But I did not double check the rpc proposal.
There was a problem hiding this comment.
Maybe trie crate api could return this enum, but the rpc return hash of the data value for inline node (this way we can avoid some hashing if this api get use by runtime in the future).
There was a problem hiding this comment.
But the spec is speaking about the merkle value and not the hash. The point being that if the data is smaller, we save bandwidth etc.
(this way we can avoid some hashing if this api get use by runtime in the future)
This doesn't add any extra hashing. If you need hashing for the runtime, we can just do it where we use it. There would be no extra hashing involved as we currently also hash the inline node manually.
There was a problem hiding this comment.
That makes sense! I've added the MerkleValue enum to be explicit about what the trie-db returns.
Then in substrate's RPC layer we could further hash(MerkleValue::Node(..)) such that we return a consistent view of nodes and not care about inline ones. And if this function gets ever called from the runtime we save a Layout:hash() call 🙏
There was a problem hiding this comment.
Then in substrate's RPC layer we could further
hash(MerkleValue::Node(..))such that we return a consistent view of nodes and not care about inline ones.
This still goes against the size argument I laid out above. I opened paritytech/json-rpc-interface-spec#88 to be sure that we use the correct value in the RPC.
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Bastian Köcher <git@kchr.de>
…1153) This PR adds support for fetching the closest merkle value of some key. Builds on top of - paritytech/trie#199 Migrates paritytech/substrate#14818 to the monorepo. Closes: paritytech/substrate#14550 Closes: #1506 // @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
…aritytech#1153) This PR adds support for fetching the closest merkle value of some key. Builds on top of - paritytech/trie#199 Migrates paritytech/substrate#14818 to the monorepo. Closes: paritytech/substrate#14550 Closes: paritytech#1506 // @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
This PR adds support for fetching the merkle value directly from the trie-db.
get_closest_merkle_valueon theTrietraitTrieDbiterates over the nibbles of the provided keyHashedValueNoExtThreshold<1>as trie layout and value update at given keyWe could build on this PR to have support for recorded Merkel Value in the cache.
Would love to get your thoughts on this @cheme @arkpar 🙏
(For reference @tomaka to ensure we don't break anything wrt to compatibilities between smoldot and substrate)
Part of paritytech/substrate#14550.
// @paritytech/subxt-team