-
Notifications
You must be signed in to change notification settings - Fork 70
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
Missing information regarding child tries #648
Comments
To clarify, I'm primarily looking for answers to these questions because I'm implementing child tries in smoldot. Adding the answers to the spec would be a bonus. Having informal answers in an issue is better than no answers at all. |
Thanks for opening the subject. I may be repeating this point a bit in the reply, but generally I think a way to think about the default/current child trie is that any child trie storage key (the part to use to fetch/store root in the top storage) does exists. This design is certainly related to the fact that child trie where initially added to implement ethereum 2 contract storage (it works this way).
It is
Yes it "creates" it, in the sense that it writes a first value in the trie, changing the root to non empty root and root will be written in the parent storage (effectively adding trie nodes in the top trie).
Ignored (no return type to the host function), could use a return boolean to indicate if there was an actual state removal (then we probably want to return false if already removed in the same block) to allow runtime to apply different weights without having to call
Simply ignored (cost at storage key access in the top trie (and a change overlay access) to realize this is already an empty trie).
Since it emptied the child trie, and an empty child trie hash is not stored in parent state (top trie), it indeed remove the child trie root from the top trie.
The child trie hash is removed from the top trie when the child trie is empty. So yes, I think at least one of these host functions returns true when it is.
So when the new child trie root is calculated (on call to storage root host function), which is something that is always done at the end of a block to get new state root, its new root is written in parent state or removed if the new root is the empty root (https://github.com/paritytech/substrate/blob/b72c475803947121b3b475eb33ba5fc48f1fe5b6/primitives/state-machine/src/backend.rs#L298).
it returns the empty root (thinking of all child trie as existing with an empty root), but do not add anything in parent trie (can remove the hash entry though).
So unless the transaction (same host function for transaction as the top trie) was reverted, the change on a previous block is always reflected in the next block. Actually the host function could be removed if a runtime do not need to access the child trie root and just use child trie as a way to store content (and possibly only access child root from rpc).
So same as previous question,
Set then remove add a child trie entry in the change overlay, but since it result in an empty child trie, nothing is written in the top trie. |
Thanks for the answer! Another question, in reaction to this: is it correct that |
Yes they clearly are redundant. (did make sense at some point because we did target a kill that is not deleting child entry one by one (or doing it asynchronously), to make the clear free of child trie accesses, but today the implementation is still removing every child trie item one by one as a clear prefix with no limit). |
It would still be nice to clarify what happens if |
For most runtime it is frame system In this case, when ext storage root is not call directly by the runtime, the client code will call it (in native) to determine the next root and pass the payload of changed db data to store. |
I have compiled a list of questions whose answer is unclear to me when it comes to child tries. These answers should IMO somehow be added to the specification.
What do
ext_default_child_storage_get_version_1
,ext_default_child_storage_read_version_1
, andext_default_child_storage_next_key
return if the specified child trie doesn't exist? I supposeNone
but clarification is important, as panicking/erroring could also be a sensible option to me. Same remark forext_default_child_storage_exists_version_1
.What happens if
ext_default_child_storage_set_version_1
is called on a child trie that doesn't exist? I suppose that it "creates" it? (the definition of "creates" is ambiguous, see other questions below)What happens if
ext_default_child_storage_clear_version_1
is called on a child trie that doesn't exist? Is the call simply ignored?What happens if
ext_default_child_storage_clear_prefix
is called on a child trie that doesn't exist? Is the call simply ignored?Does
ext_default_child_storage_storage_kill
destroy the child trie entirely? If yes, this isn't mention in the spec.Assuming that the answer to 5) is yes, is it correct that in the case of
ext_default_child_storage_storage_kill_version_2
andext_default_child_storage_storage_kill_version_3
the child trie is destroyed only if the limit is not reached?Assuming that the answer to 5) is yes, does
ext_default_child_storage_storage_kill
also automatically erase the:child_storage:default:
key in the main trie? In other words, if you callext_default_child_storage_storage_kill("foo"); ext_storage_get_version_1(":child_storage:default:foo")
, doesext_storage_get_version_1
returnSome
orNone
?What happens if
ext_default_child_storage_root
is called on a child trie that doesn't exist? Does it create an empty trie and return an empty trie hash? Or does it instead error/panic?What happens if you call
ext_default_child_storage_set_version_1("foo", "bar")
, then you don't callext_default_child_storage_root
, and then in the next block you callext_default_child_storage_get_version_1("foo", "bar")
? Doesext_default_child_storage_get_version_1
returnSome
orNone
?What happens if you call
ext_default_child_storage_root
, thenext_default_child_storage_set_version_1("foo", "bar")
, then you don't callext_default_child_storage_root
, and then in the next block you callext_storage_get_version_1(":child_storage:default:foo")
? Is the value returned byext_storage_get_version_1
equal to the one thatext_default_child_storage_root
returned?Assuming that child trie
"foo"
doesn't exist yet, what happens if you callext_default_child_storage_set_version_1("foo", "bar")
thenext_default_child_storage_clear_version_1("foo", "bar")
, then you don't callext_default_child_storage_root
, and in the next block you callext_storage_get_version_1(":child_storage:default:foo")
? Doesext_storage_get_version_1
returnSome
orNone
??The text was updated successfully, but these errors were encountered: