-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Introduce new storage type: prefixed map #3992
Conversation
Prefixed map is a new storage available in decl_storage, it differ from map as it stores it keys at `twox_256(prefix)++map_hasher(key)` instead of `map_hasher(prefix ++ key)`. Thus it allows to remove all key of the map using `sr-io::kill_prefix`, but the final goal is to also allow to iter on the map once sr-io make such call available.
|
This looks like substrate/srml/system/src/lib.rs Line 416 in ec7c6cf
|
|
It's not so great to have a long, insecure hash as the first key as it's not inconceivable that someone could craft a module which intentionally has storage keys that collided with another module. A better way of forming the first key could be to simply append a short twox hash (8 byte, perhaps) of the item name to either the module name or a twox hash of it. This more or less guarantees it being unrealistic to craft a storage item collision, at least making it super-obvious in the module name. |
|
So finally we will do instead of a new storage type just an optional attribute on linked_map stored at (Or otherwise we could also make use of blake2hasher if we can ensure this is done at compile time but I prefer the first way) I'll work on this starting monday next week after my days off |
|
sounds good. |
|
As we want to remove |
|
how far off is this? i could do with it for a PR i'm working on... |
|
in particular, i could do with iteration on a |
|
for double_map you want to iterate over all values? I can implement But if you want to iterate on first keys only it seems it requires new function in sr-io. |
|
superseeded by #4185 |
Context
Prefixed map is a new storage available in decl_storage.
it differ from map as it stores it keys at
twox_256(prefix)++map_hasher(key)instead ofmap_hasher(prefix ++ key).Thus it allows to remove all key of the map using
sr-io::kill_prefix.But the final goal is to make it also iterable using #3883
In the end this should replace linked_map as iteration is more efficient (just there is no longer ordering). and also Maps as it allows to have more functionality
To discuss:
should we directly put this in a child trie instead of behind a prefix in top trie ?
the value is stored at
twox_256(prefix)++map_hasher(key):the first part is using twox_256 for hashing the prefix because we have to be sure that no other value share the same prefix. in case we only use twox_128 then an attacker could try to craft a key which have blake2_256(key)[0..16] == twox_128(prefix). Thus inserting a wrong value into this map.
Introducing this map has the consequence to limit the size of our hashers. introducing a hasher with an output longer than 256 bit is no longer relevant as it can already collision with this map.
If this is an issue then it can be solve in two way:
sr-io::kill_prefix_with_size(MAP_PREFIX, 32+size_of_map_hasher)the second part is map_hasher(key). currently a hasher is mandatory though it seems it could be interesting to introduce a no_hasher variant (or hasher=identity). thus value would be stored at
twox_256(prefix) ++ key.encode(). The only interest I see from this is that it would avoid some hasher call.