Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Implements pallet versioning #7208

Merged
merged 22 commits into from
Oct 21, 2020
Merged

Implements pallet versioning #7208

merged 22 commits into from
Oct 21, 2020

Conversation

bkchr
Copy link
Member

@bkchr bkchr commented Sep 24, 2020

This pull requests adds a new struct PalletVersion. This struct holds the members major, minor and patch to reflect the version of a crate.

The pallet version will be automatically bound to each pallet, this means on each time the runtime is upgraded and on_runtime_upgrade is called, the latest pallet version is stored in the state. This can be used on a later runtime upgrade to check which kinds of upgrades need to be applied. There is only one point in time where the actual version of a pallet and the version of a pallet in the storage is different and that is after a runtime upgrade and before on_runtime_upgrade of the pallet was called to update the version.

There is also a new trait GetPalletVersion provided. This trait will be automatically implemented by each pallet. It can be used from the runtime to get the versions of each pallet.

Besides that there is also a new macro crate_to_pallet_version!. This converts the version of the current crate into a PalletVersion object.

After this pr we should make sure that we update the crate versions accordingly to changes, to make sure we can write upgrades accordingly.

@jacogr maybe this is also something that can be supported from the UI to read the versions per pallet.

addresses #6888

@bkchr bkchr added A0-please_review Pull request needs code review. B7-runtimenoteworthy C1-low PR touches the given topic and has a low impact on builders. labels Sep 24, 2020
/// The storage key postfix that is used to store the [`PalletVersion`] per pallet.
///
/// The full storage key is build by using:
/// Twox128([`PalletInfo::name`] ++ [`PALLET_VERSION_STORAGE_POSTFIX`])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not Twox128([PalletInfo::name]) ++ Twox128([PALLET_VERSION_STORAGE_POSTFIX]) in order to keep the fact that all usage of a pallet is after some prefix.

Thus once we make pallet storages using PalletInfo::name then we have all pallet storage usage after a unique prefix.
This would ease removal and introspection IMHO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that sounds good as well;)

frame/support/test/tests/pallet_version.rs Show resolved Hide resolved
@@ -1320,19 +1323,40 @@ macro_rules! decl_module {
{
fn on_runtime_upgrade() -> $return {
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade"));
{ $( $impl )* }
let result = { $( $impl )* };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if user write return Ok(..); inside the impl block, I think they would expect to have storage version written.
Maybe it is better to wrap it into a closure or something, no ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point

frame/support/src/traits.rs Outdated Show resolved Hide resolved
frame/support/src/traits.rs Outdated Show resolved Hide resolved
frame/support/src/traits.rs Outdated Show resolved Hide resolved
frame/support/src/traits.rs Outdated Show resolved Hide resolved
@apopiak
Copy link
Contributor

apopiak commented Sep 26, 2020

I just want to note the edgecase that I recently saw in the UTXO runtime where the crate of the pallet was the same as the crate of the runtime.
Should still work, right?
And: do we want to support pallets that are not part of a (cargo) crate?

Copy link
Contributor

@apopiak apopiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply typo suggestions

@bkchr
Copy link
Member Author

bkchr commented Oct 20, 2020

Sorry for the long quite period.

I'm still in favor of this pallet versioning scheme:

  1. It solves the problem of having a storage versioning scheme. We can just as discussed widely in this pr use the pallet version to check for required migrations etc. While this could be solved with a simple storage version as proposed by @thiolliere, I don't see any reason why not use the pallet version as well.
  2. I see pallet versioning more useful in the future, when we really have multiple versions of a crate being deployed on different chains. Currenty the UI needs to do some magic to find out which version a crate is and what it can do or if there are certain bugs that it needs to circumvent. By using pallet versioning, we can make this much easier. External software can read the version of a pallet and act accordingly.
  3. While pallets are a DSL that is written in Rust and it is sort of special, I don't see a reason why we should invent different mechanism for all the stuff. Why not use the crate version as input for the pallet version? Why should we come up with something different, that in the end wants to solve the same problem. Yeah, we will need some thinking around semver and how to integrate it in pallets, but why not do this and teach our users on how it should be done, like Rust is doing it.
  4. We can still bring in a model where the user manually specifies the version, instead of automatically using the crate version. This could be helpful for crates which host different pallets or just for people who don't like using the crate version as pallet version. However this doesn't mean that we will need to change the structure of the pallet version struct and thus, we will stay compatible.

Copy link
Contributor

@gui1117 gui1117 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

I agree we can use crate version, later if user request to be able to set it inside the pallet then we can introduce it without breaking.

frame/support/src/dispatch.rs Outdated Show resolved Hide resolved
frame/support/src/dispatch.rs Outdated Show resolved Hide resolved
bkchr and others added 2 commits October 20, 2020 15:49
Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Copy link
Contributor

@apopiak apopiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bkchr bkchr merged commit 529e5d9 into master Oct 21, 2020
@bkchr bkchr deleted the bkchr-pallet-version branch October 21, 2020 17:05
@kianenigma
Copy link
Contributor

Would be interesting to see this in action in a PR that does some migration :) Do we already happen to have one?

@apopiak
Copy link
Contributor

apopiak commented Oct 22, 2020

Well how about #7040? ;-)

@apopiak
Copy link
Contributor

apopiak commented Oct 22, 2020

@bkchr Just realized that we only set the version on_runtime_upgrade and thus don't set the version on initial launch of a chain, correct?

@apopiak
Copy link
Contributor

apopiak commented Oct 22, 2020

Would be interesting to see this in action in a PR that does some migration :) Do we already happen to have one?

I think I'm also going to create a dummy migration PR to test this stuff :-)

@bkchr
Copy link
Member Author

bkchr commented Oct 22, 2020

@bkchr Just realized that we only set the version on_runtime_upgrade and thus don't set the version on initial launch of a chain, correct?

Ohh yeah 🙈 I did not thought about this. Give me some time to find a good solution.

///
/// Each pallet version is stored in the state under a fixed key. See
/// [`PALLET_VERSION_STORAGE_KEY_POSTFIX`] for how this key is built.
#[derive(RuntimeDebug, Eq, PartialEq, Encode, Decode, Ord)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late comments/nitpicks, but I wonder whether this should be Copy or at least Clone.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. C1-low PR touches the given topic and has a low impact on builders.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants