3

I am trying to understand the usage of the translate function that is frequently used when writing migrations.

Is this function only being used to do changes to some existing storage values(I don't think so since why would it be different than the map function)? For example, iterating through a StorageMap of u32s and increasing the values by 1. Or is it also possible to use this function to adapt the data for the new type that is being stored for example in a StorageMap? And if so how could something like that be achieved?

I haven't found any detailed documentation about this.

1 Answer 1

2

translate, as opposed to mutate or map, can be used to translate values between types.
It is sometimes used in storage migration exactly for that possibility.

Imagine a scenario like this:

  • There is a pallet which stores OldInfo in a StorageMap called MyMap
  • Now a migration should translate all OldInfo into NewInfo in that map
MyMap::translate::<OldInfo, _>(|_key, old| -> Option<NewInfo> {
    Some(old.to_new_format())
})

Would archive this.

I personally never use translate since it has a flaw. From the docs:

NOTE: If a value fail to decode because storage is corrupted then it is skipped.

This means that if you have a type error in your migration by providing a faulty old type, it will just do nothing and carry over these old values silently.
This is harder to mess up when using a storage_alias.

It is probably a good idea in any case to check that all values still decode in the post-migration hook:

assert_eq!(MyMap::iter_values().count(), number_of_decodable_elements);
6
  • What does this exactly mean it will just do nothing and carry over these old values silently? Assume this happens, then we have still the old storage structure in the storage item. What happens then, when I query the storage after the faulty migration?
    – Chralt
    Commented Jan 6, 2023 at 8:53
  • What would you suggest instead of translate? Assume you have an old storage structure and want to migrate to a new one. I mean when you use storage_iter or storage_key_iter you also need to specify how to decode the values. You could also have a wrong storage structure specified as the decoding struct.
    – Chralt
    Commented Jan 6, 2023 at 8:56
  • What is a storage alias and how to use it? EDIT: Look here substrate.stackexchange.com/questions/3252/…
    – Chralt
    Commented Jan 6, 2023 at 8:57
  • github.com/paritytech/substrate/blob/… After the upgrade and faulty migration a new get query to the storage will fail to decode the new storage structure, right? This means, that then you can't access your storage anymore with the wrong decoding and you have to revert the storage structure for your runtime?
    – Chralt
    Commented Jan 6, 2023 at 9:18
  • 1
    Rather iterate manually than use translate. Like this. You can also use iter_keys vs iter_values to find undecodable values and remove them in the migration like here. But be careful not to modify the map while iterating and instead always call collect() first. Please ask a new Q about the storage_alias. Commented Jan 6, 2023 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.