Move runtime upgrade to frame-executive (#5197)

* Move runtime upgrade to `frame-executive`

Instead of storing the runtime upgraded in the space of `frame-system`,
this moves it to `frame-executive`. We also start storing the
`spec_version` and `impl_version` the last runtime upgrade was applied.

This scheme has multiple advantages:
- We don't need to make sure that runtime upgrade was set.
- This will work in the future when we want to test a runtime upgrade,
because the `on_runtime_upgrade` will be executed automatically when the
runtime changes.

* Move `LAST_RUNTIME_UPGRADE` key to `frame-executive`

* Add some more documentation

* Make sure `spec_version` always increases between runtime upgrades

* Fix test

* Upgrade `parity-multiaddr` to fix compilation

* Also check if the `spec_name` changed

* Remove `RuntimeUpgraded` storage entry

* Don't run on genesis
This commit is contained in:
Bastian Köcher
2020-03-15 20:28:57 +01:00
committed by GitHub
parent b57fd17998
commit 26fa6e3c76
7 changed files with 156 additions and 47 deletions
+43 -30
View File
@@ -307,6 +307,33 @@ pub struct AccountInfo<Index, AccountData> {
pub data: AccountData,
}
/// Stores the `spec_version` and `spec_name` of when the last runtime upgrade
/// happened.
#[derive(sp_runtime::RuntimeDebug, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub struct LastRuntimeUpgradeInfo {
pub spec_version: codec::Compact<u32>,
pub spec_name: sp_runtime::RuntimeString,
}
impl LastRuntimeUpgradeInfo {
/// Returns if the runtime was upgraded in comparison of `self` and `current`.
///
/// Checks if either the `spec_version` increased or the `spec_name` changed.
pub fn was_upgraded(&self, current: &sp_version::RuntimeVersion) -> bool {
current.spec_version > self.spec_version.0 || current.spec_name != self.spec_name
}
}
impl From<sp_version::RuntimeVersion> for LastRuntimeUpgradeInfo {
fn from(version: sp_version::RuntimeVersion) -> Self {
Self {
spec_version: version.spec_version.into(),
spec_name: version.spec_name,
}
}
}
decl_storage! {
trait Store for Module<T: Trait> as System {
/// The full account information for a particular account ID.
@@ -368,8 +395,8 @@ decl_storage! {
/// no notification will be triggered thus the event might be lost.
EventTopics get(fn event_topics): map hasher(blake2_256) T::Hash => Vec<(T::BlockNumber, EventIndex)>;
/// A bool to track if the runtime was upgraded last block.
pub RuntimeUpgraded: bool;
/// Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened.
pub LastRuntimeUpgrade build(|_| Some(LastRuntimeUpgradeInfo::from(T::Version::get()))): Option<LastRuntimeUpgradeInfo>;
}
add_extra_genesis {
config(changes_trie_config): Option<ChangesTrieConfiguration>;
@@ -416,13 +443,7 @@ decl_error! {
InvalidSpecName,
/// The specification version is not allowed to decrease between the current runtime
/// and the new runtime.
SpecVersionNotAllowedToDecrease,
/// The implementation version is not allowed to decrease between the current runtime
/// and the new runtime.
ImplVersionNotAllowedToDecrease,
/// The specification or the implementation version need to increase between the
/// current runtime and the new runtime.
SpecOrImplVersionNeedToIncrease,
SpecVersionNeedsToIncrease,
/// Failed to extract the runtime version from the new runtime.
///
/// Either calling `Core_version` or decoding `RuntimeVersion` failed.
@@ -478,18 +499,11 @@ decl_module! {
Err(Error::<T>::InvalidSpecName)?
}
if new_version.spec_version < current_version.spec_version {
Err(Error::<T>::SpecVersionNotAllowedToDecrease)?
} else if new_version.spec_version == current_version.spec_version {
if new_version.impl_version < current_version.impl_version {
Err(Error::<T>::ImplVersionNotAllowedToDecrease)?
} else if new_version.impl_version == current_version.impl_version {
Err(Error::<T>::SpecOrImplVersionNeedToIncrease)?
}
if new_version.spec_version <= current_version.spec_version {
Err(Error::<T>::SpecVersionNeedsToIncrease)?
}
storage::unhashed::put_raw(well_known_keys::CODE, &code);
RuntimeUpgraded::put(true);
Self::deposit_event(RawEvent::CodeUpdated);
}
@@ -498,7 +512,6 @@ decl_module! {
pub fn set_code_without_checks(origin, code: Vec<u8>) {
ensure_root(origin)?;
storage::unhashed::put_raw(well_known_keys::CODE, &code);
RuntimeUpgraded::put(true);
Self::deposit_event(RawEvent::CodeUpdated);
}
@@ -526,9 +539,6 @@ decl_module! {
ensure_root(origin)?;
for i in &items {
storage::unhashed::put_raw(&i.0, &i.1);
if i.0 == well_known_keys::CODE {
RuntimeUpgraded::put(true);
}
}
}
@@ -558,6 +568,13 @@ decl_module! {
ensure!(account.data == T::AccountData::default(), Error::<T>::NonDefaultComposite);
Account::<T>::remove(who);
}
fn on_runtime_upgrade() {
// Remove the old `RuntimeUpgraded` storage entry.
let mut runtime_upgraded_key = sp_io::hashing::twox_128(b"System").to_vec();
runtime_upgraded_key.extend(&sp_io::hashing::twox_128(b"RuntimeUpgraded"));
sp_io::storage::clear(&runtime_upgraded_key);
}
}
}
@@ -1935,12 +1952,12 @@ mod tests {
}
let test_data = vec![
("test", 1, 2, Ok(())),
("test", 1, 1, Err(Error::<Test>::SpecOrImplVersionNeedToIncrease)),
("test", 1, 2, Err(Error::<Test>::SpecVersionNeedsToIncrease)),
("test", 1, 1, Err(Error::<Test>::SpecVersionNeedsToIncrease)),
("test2", 1, 1, Err(Error::<Test>::InvalidSpecName)),
("test", 2, 1, Ok(())),
("test", 0, 1, Err(Error::<Test>::SpecVersionNotAllowedToDecrease)),
("test", 1, 0, Err(Error::<Test>::ImplVersionNotAllowedToDecrease)),
("test", 0, 1, Err(Error::<Test>::SpecVersionNeedsToIncrease)),
("test", 1, 0, Err(Error::<Test>::SpecVersionNeedsToIncrease)),
];
for (spec_name, spec_version, impl_version, expected) in test_data.into_iter() {
@@ -1980,8 +1997,6 @@ mod tests {
System::events(),
vec![EventRecord { phase: Phase::ApplyExtrinsic(0), event: 102u16, topics: vec![] }],
);
assert_eq!(RuntimeUpgraded::get(), true);
});
}
@@ -1998,8 +2013,6 @@ mod tests {
substrate_test_runtime_client::runtime::WASM_BINARY.to_vec()
)],
).unwrap();
assert_eq!(RuntimeUpgraded::get(), true);
});
}
}