substrate
substrate copied to clipboard
How should we use ChildTrie unique_id ? what constrain and property should we follow.
Similarly to what has been done for storages in the main trie, we should introduce the habits of prefixing the child storage key with the hash of the module name so we can distinguish who this child storage is belonging to.
Currently in substrate only contracts uses child storage and in polkadot crowdfund. My proposal is to make all contract childtries after having the prefix twox_64("contracts-child-tries") and all childtries of crowdfund having the prefix twox_64("crowdfund-child-tries").
Note that this change works well with https://github.com/paritytech/polkadot-sdk/issues/363
As if a pallet choose to be inside a childtrie then we would have in the pallet in the childtrie twox_64("PalletPrefix") and all its childtries prefixed with twox_64("PalletPrefix-child-tries").
I'm not sure about the hash there is seems someone could craft a pallet prefix so that it collides with other as twox64 is weak.
I'm not sure about how unique_id of child trie should be choosen, this is important for https://github.com/paritytech/polkadot-sdk/issues/363 and https://github.com/paritytech/substrate/issues/4707
It seems if we want to avoid having some collision between childtrie ensuring a length of 256 bit is a good decision.
The unique_id used by childtries will prefix the database key (nodes hash) (different from the key in the trie which could be named path). If you use "abc" as unique_id all the database key used by your child trie will have the prefix "abc". On batch deletion (which is not implemented but one of the goal of childtries) the client will remove all database key starting with this prefix, thus no other key must start with the same prefix.
So a collision can happen:
- Between two childtries if one unique_id is the start of another one.
Thus if we use just
twox_64("module_foo")for the unique_id of the child trie and at the same time keep contracts using blake2_256 of some stuff, if contracts user can generate the contract address they want then they just need to attack the first 64bit and in case the module foo removes its child trie then the contract will be removed as well (So the security of the hash blake2_256 can actually attack by only crafting the first 64bit). - Between a childtrie and the top trie.
top trie node (and childtrie node as well) are stored in the database actually not at the key
hash(node)but actually a combination of this hash of itself and the path to access this node. (I don't know details). But knowing this if somebody successfully create some nodes with a key that start with some unique_id then this nodes will be removed if the childtrie is removed.
Considering those two attacks From those two kind of collision it seems to me we should always use a unique_id of length at least 256, and thus attacker must attack 256bit. and thus we can use blake2_256 of untrusted input.
I'm very open to suggestion about how we should make use of this space.