-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Introduce on_runtime_upgrade similarly to on_initialize but executed before. #4056
Comments
note: even if we execute on_runtime_upgrade just before on_initialize of next block we still have some logic executing in between for validating transaction: such logic is regular validate transaction but also the per-pallet defined signed extensions, this signed extensions logic could fail. Maybe the validate_transaction could return an error with Either on all transaction but that means having an empty block after each upgrade (which looks fine) or only for transaction that have some signed extension define in module. EDIT: having an empty block after an update looks very fine to me actually, or making the queue aware that transactions invalid for this block should be kept. |
note: the staking module has update its storage one time, you can see an example of a migration code in frame/staking/src/migration.rs This kind of transition work for staking but in case of SignedExtensions this has one caveat the validation of transaction in the queue could panic, thus probably having them removed from the queue. Or the signed extension validation should do the storage migration, but then this validation function can cost a lot. |
Expanding on this idea, it is very possible that post-runtime-upgrade functions may want to execute logic which would take more than a single block. In magical dream land, For example: Let's imagine we want to update the balances module of a live chain such that the balance type is u256 rather than u128 or something like that. With thousands, maybe millions of accounts, a storage upgrade (#4555) would not complete in just one block. But, if a runtime developer could simply write in the As long as there is still some |
we could also think as non-blocking migration, like we create a new storages and do as such:
|
Yes, a lazy migration pattern would also be very useful. |
How would you know that the item was already migrated? |
You would be able to check |
Why would the key change? And if we had 2 keys, we would need to check both keys until the end of the universe, which also requires to have one extra storage access, each time. |
my idea for lazy_migration was to do this as well:
Then after some block the entire storage1 will be empty thus we no longer need to check it. It would be a performance regression for only the time of the migration. |
With the recent introduction of StorageValue::translate a new pattern appeared in on_initialize:
The error proneness is that on_initialize are executed in the order declaration in construct_runtime. Thus if one upper module in on_initialize call your module and use this storage, then the value is still the old encoded one. And thus can leads to very error.
To solve this we can introduce a new function: on_runtime_upgrade_initialize which will be call before all on_initialize.
With this the code to check is just the code contained in on_runtime_upgrade_initialize of other module which logic is easier to audit.
cc @shawntabrizi
The text was updated successfully, but these errors were encountered: