-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Initialise on-chain StorageVersion for pallets added after genesis
#1297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
ca1db8c
1c44c96
1ab2eca
1d84c1a
a2a6078
011ec33
f12dcb1
9e0980a
a0ff4b7
06e0b10
62c4c3d
6a66617
68183e9
f30da51
bb0915e
c4d7f40
d7ed843
2319a51
41cb160
d30765f
18a1f82
bc50779
11b33aa
7dccbf6
6919547
5b196f1
5f00efa
031da73
a552b6b
43b587e
dfe7347
dcd7595
40e6035
fc09aff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,6 +99,22 @@ pub trait OnGenesis { | |
| fn on_genesis() {} | ||
| } | ||
|
|
||
| /// Implemented by pallets, allows defining logic to run prior to any [`OnRuntimeUpgrade`] logic. | ||
| /// | ||
| /// This was introduced to allow pallets to initialize their on-chain storage version in the case | ||
| /// that they are added to the runtime after genesis. | ||
| /// | ||
liamaharon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// This hook is intended to be used internally in FRAME and not be exposed to FRAME developers. | ||
| /// | ||
| /// It is defined as a seperate trait from [`OnRuntimeUpgrade`] precisely to not pollute the public | ||
| /// API. | ||
| pub trait BeforeAllRuntimeMigrations { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in principle we can
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds good, are you able to point me in the direction for how that could be achieved?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can not do this. There is no way to only allow our macros to implement a trait.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was hinting at the trait sealing technique but indeed it doesn't properly work here, because the trait that I am intending to seal is implemented at the end of the day by We could still semi-seal it by putting the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| /// Something that should happen before runtime migrations are executed. | ||
| fn before_all_runtime_migrations() -> Weight { | ||
| Weight::zero() | ||
| } | ||
| } | ||
|
|
||
| /// See [`Hooks::on_runtime_upgrade`]. | ||
| pub trait OnRuntimeUpgrade { | ||
| /// See [`Hooks::on_runtime_upgrade`]. | ||
|
|
@@ -150,10 +166,24 @@ pub trait OnRuntimeUpgrade { | |
| } | ||
| } | ||
|
|
||
| #[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] | ||
| #[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] | ||
| #[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] | ||
| impl BeforeAllRuntimeMigrations for Tuple { | ||
| /// Implements the default behavior of | ||
| /// [`BeforeAllRuntimeMigrations::before_all_runtime_migrations`] for tuples. | ||
| fn before_all_runtime_migrations() -> Weight { | ||
| let mut weight = Weight::zero(); | ||
| for_tuples!( #( weight = weight.saturating_add(Tuple::before_all_runtime_migrations()); )* ); | ||
| weight | ||
| } | ||
| } | ||
|
|
||
| #[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))] | ||
| #[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))] | ||
| #[cfg_attr(feature = "tuples-128", impl_for_tuples(128))] | ||
| impl OnRuntimeUpgrade for Tuple { | ||
| /// Implements the default behavior of [`OnRuntimeUpgrade::on_runtime_upgrade`] for tuples. | ||
| fn on_runtime_upgrade() -> Weight { | ||
| let mut weight = Weight::zero(); | ||
| for_tuples!( #( weight = weight.saturating_add(Tuple::on_runtime_upgrade()); )* ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2329,6 +2329,55 @@ fn test_storage_alias() { | |
| }) | ||
| } | ||
|
|
||
| #[test] | ||
| fn pallet_on_chain_storage_version_initializes_correctly() { | ||
| type Executive = frame_executive::Executive< | ||
| Runtime, | ||
| Block, | ||
| frame_system::ChainContext<Runtime>, | ||
| Runtime, | ||
| AllPalletsWithSystem, | ||
| >; | ||
|
|
||
| // Simple example of a pallet with current version 10 being added to the runtime for the first | ||
| // time. | ||
| TestExternalities::default().execute_with(|| { | ||
| let current_version = Example::current_storage_version(); | ||
|
|
||
| // Check the on-chain storage version initially is not set and does not match the current | ||
| // version. | ||
| let on_chain_version_before = StorageVersion::get::<Example>(); | ||
| assert_eq!(StorageVersion::exists::<Example>(), false); | ||
| assert_ne!(on_chain_version_before, current_version); | ||
|
|
||
| // [`frame_support::traits::BeforeAllRuntimeMigrations`] hook should initialize the storage | ||
| // version. | ||
| Executive::execute_on_runtime_upgrade(); | ||
|
|
||
| // Check that the storage version was initialized to the current version | ||
| let on_chain_version_after = StorageVersion::get::<Example>(); | ||
| assert_eq!(on_chain_version_after, current_version); | ||
| }); | ||
|
|
||
| // Pallet with no current storage version should have the on-chain version initialized to 0. | ||
| TestExternalities::default().execute_with(|| { | ||
| // Example4 current_storage_version is NoStorageVersionSet. | ||
|
|
||
| // Check the storage version is not set and implicitly 0. | ||
| let on_chain_version_before = StorageVersion::get::<Example4>(); | ||
| assert_eq!(StorageVersion::exists::<Example4>(), false); | ||
| assert_eq!(on_chain_version_before, StorageVersion::new(0)); | ||
|
|
||
| // [`frame_support::traits::BeforeAllRuntimeMigrations`] initializes the storage version. | ||
| Executive::execute_on_runtime_upgrade(); | ||
|
|
||
| // Check that the storage version now exists and was initialized to 0. | ||
| let on_chain_version_after = StorageVersion::get::<Example4>(); | ||
| assert_eq!(StorageVersion::exists::<Example4>(), true); | ||
| assert_eq!(on_chain_version_after, StorageVersion::new(0)); | ||
| }); | ||
| } | ||
|
|
||
| #[cfg(feature = "try-runtime")] | ||
| #[test] | ||
| fn post_runtime_upgrade_detects_storage_version_issues() { | ||
|
|
@@ -2381,8 +2430,10 @@ fn post_runtime_upgrade_detects_storage_version_issues() { | |
| >; | ||
|
|
||
| TestExternalities::default().execute_with(|| { | ||
| // Call `on_genesis` to put the storage version of `Example` into the storage. | ||
| Example::on_genesis(); | ||
|
Comment on lines
-2385
to
-2386
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test used to rely on Updated this test to work with the new system where initialisation is automatic, but once the version is initialised the dev will need to apply migrations to keep on-chain and current versions consistent. |
||
| // Set the on-chain version to one less than the current version for `Example`, simulating a | ||
| // forgotten migration | ||
| StorageVersion::new(9).put::<Example2>(); | ||
|
|
||
| // The version isn't changed, we should detect it. | ||
| assert!( | ||
| Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap_err() == | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.