-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Use Mandatory Indices for FRAME Storage API (and others) #8964
Description
The FRAME storage APIs use a combination of prefixes to describe the location of storage items. Something like:
hash(pallet_name) + hash(storage_name) + hash(key_value) + ...
We have seen multiple times where this has come to bite us in the butt:
- Recent migrations from frame v1 -> v2 where we changed the string used for the hasher
- Any changes to the name of a storage item (typos, better clarification, etc....)
Similarly, we ran into issues with Construct Runtime and the ordering of pallets, and the call enum and ordering of extrinsics.
My suggestion is that we should use indexes, not human strings / variable names, wherever there could be some breaking change caused by reorganization, renaming, refactoring, etc...
Protobuf follows a similar philosophy: https://developers.google.com/protocol-buffers/docs/overview
I believe the following FRAME objects should use explicitly defined indexes:
- Pallets in Construct Runtime
- Calls in Pallet
- Storage in Pallet
Items which are not breaking need not have explicit ordering, but should allow optional explicit ordering:
- Errors in Pallet
- Events in Pallet
When defining a storage item with the FRAME v2 macros, users should be required(?) to include an explicit index:
#[pallet::storage]
#[pallet::storage::index(0)] <-- this
#[pallet::getter(fn auction_counter)]
pub type AuctionCounter<T> = StorageValue<_, AuctionIndex, ValueQuery>;
We already support and require indices on Pallet ordering in construct runtime. This is needed for transaction versioning.
Combining these two, the new storage pattern should be:
hash(pallet_index) + hash(storage_index) + hash(key_value) + ...
In this case, we can update the name of the storage or move the storage definition to anywhere in the source code, and not break your pallet.
We still want to hash these indices so that pallet storage is in its own trie branch.
We have also wanted to put all pallet storage into its own child trie, so maybe we should do that here too.