-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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
@@ -644,6 +644,80 @@ fn test_recorder_with_cache_get_hash_internal<T: TrieLayout>() { | |||
} | |||
} | |||
|
|||
#[test] | |||
fn test_merkle_value() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lexnv , thanks for the work, I got a few question on corner cases, notably inline node (I am not 100% sure, depends of how the spec is understood).
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>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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_value
on theTrie
traitTrieDb
iterates 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