Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 32 additions & 26 deletions substrate/frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,12 @@ where
let mut weight = Weight::zero();
if Self::runtime_upgraded() {
weight = weight.saturating_add(Self::execute_on_runtime_upgrade());

frame_system::LastRuntimeUpgrade::<System>::put(
frame_system::LastRuntimeUpgradeInfo::from(
<System::Version as frame_support::traits::Get<_>>::get(),
),
);
}
<frame_system::Pallet<System>>::initialize(block_number, parent_hash, digest);
weight = weight.saturating_add(<AllPalletsWithSystem as OnInitialize<
Expand All @@ -503,19 +509,14 @@ where
frame_system::Pallet::<System>::note_finished_initialize();
}

/// Returns if the runtime was upgraded since the last time this function was called.
/// Returns if the runtime was upgraded.
///
/// based on [`frame_system::LastRuntimeUpgrade`]
fn runtime_upgraded() -> bool {
let last = frame_system::LastRuntimeUpgrade::<System>::get();
let current = <System::Version as frame_support::traits::Get<_>>::get();

if last.map(|v| v.was_upgraded(&current)).unwrap_or(true) {
frame_system::LastRuntimeUpgrade::<System>::put(
frame_system::LastRuntimeUpgradeInfo::from(current),
);
true
} else {
false
}
last.map(|v| v.was_upgraded(&current)).unwrap_or(true)
}

fn initial_checks(block: &Block) {
Expand Down Expand Up @@ -755,7 +756,7 @@ mod tests {
traits::{fungible, ConstU32, ConstU64, ConstU8, Currency},
weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee},
};
use frame_system::{ChainContext, LastRuntimeUpgradeInfo};
use frame_system::{ChainContext, LastRuntimeUpgrade, LastRuntimeUpgradeInfo};
use pallet_balances::Call as BalancesCall;
use pallet_transaction_payment::CurrencyAdapter;

Expand Down Expand Up @@ -994,6 +995,9 @@ mod tests {
sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes());
sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode());
System::deposit_event(frame_system::Event::CodeUpdated);

assert_eq!(0, System::last_runtime_upgrade_spec_version());

Weight::from_parts(100, 0)
}
}
Expand Down Expand Up @@ -1356,17 +1360,13 @@ mod tests {
new_test_ext(1).execute_with(|| {
RuntimeVersionTestValues::mutate(|v| *v = Default::default());
// It should be added at genesis
assert!(frame_system::LastRuntimeUpgrade::<Runtime>::exists());
assert!(LastRuntimeUpgrade::<Runtime>::exists());
assert!(!Executive::runtime_upgraded());

RuntimeVersionTestValues::mutate(|v| {
*v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() }
});
assert!(Executive::runtime_upgraded());
assert_eq!(
Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "".into() }),
frame_system::LastRuntimeUpgrade::<Runtime>::get(),
);

RuntimeVersionTestValues::mutate(|v| {
*v = sp_version::RuntimeVersion {
Expand All @@ -1376,27 +1376,18 @@ mod tests {
}
});
assert!(Executive::runtime_upgraded());
assert_eq!(
Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }),
frame_system::LastRuntimeUpgrade::<Runtime>::get(),
);

RuntimeVersionTestValues::mutate(|v| {
*v = sp_version::RuntimeVersion {
spec_version: 1,
spec_name: "test".into(),
spec_version: 0,
impl_version: 2,
..Default::default()
}
});
assert!(!Executive::runtime_upgraded());

frame_system::LastRuntimeUpgrade::<Runtime>::take();
LastRuntimeUpgrade::<Runtime>::take();
assert!(Executive::runtime_upgraded());
assert_eq!(
Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }),
frame_system::LastRuntimeUpgrade::<Runtime>::get(),
);
})
}

Expand Down Expand Up @@ -1444,6 +1435,10 @@ mod tests {

assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module");
assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode());
assert_eq!(
Some(RuntimeVersionTestValues::get().into()),
LastRuntimeUpgrade::<Runtime>::get(),
)
});
}

Expand Down Expand Up @@ -1519,6 +1514,11 @@ mod tests {

#[test]
fn all_weights_are_recorded_correctly() {
// Reset to get the correct new genesis below.
RuntimeVersionTestValues::mutate(|v| {
*v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() }
});

new_test_ext(1).execute_with(|| {
// Make sure `on_runtime_upgrade` is called for maximum complexity
RuntimeVersionTestValues::mutate(|v| {
Expand All @@ -1535,6 +1535,12 @@ mod tests {
Digest::default(),
));

// Reset the last runtime upgrade info, to make the second call to `on_runtime_upgrade`
// succeed.
LastRuntimeUpgrade::<Runtime>::set(Some(
sp_version::RuntimeVersion { spec_version: 0, ..Default::default() }.into(),
));

// All weights that show up in the `initialize_block_impl`
let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade();
let runtime_upgrade_weight =
Expand Down
1 change: 1 addition & 0 deletions substrate/frame/system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ sp-runtime = { path = "../../primitives/runtime", default-features = false, feat
sp-std = { path = "../../primitives/std", default-features = false}
sp-version = { path = "../../primitives/version", default-features = false, features = ["serde"] }
sp-weights = { path = "../../primitives/weights", default-features = false, features = ["serde"] }
docify = "0.2.0"

[dev-dependencies]
criterion = "0.4.0"
Expand Down
19 changes: 19 additions & 0 deletions substrate/frame/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,25 @@ pub enum DecRefStatus {
}

impl<T: Config> Pallet<T> {
/// Returns the `spec_version` of the last runtime upgrade.
///
/// This function is useful for writing guarded runtime migrations in the runtime. A runtime
/// migration can use the `spec_version` to ensure that it isn't applied twice. This works
/// similar as the storage version for pallets.
///
/// This functions returns the `spec_version` of the last runtime upgrade while executing the
/// runtime migrations
/// [`on_runtime_upgrade`](frame_support::traits::OnRuntimeUpgrade::on_runtime_upgrade)
/// function. After all migrations are executed, this will return the `spec_version` of the
/// current runtime until there is another runtime upgrade.
///
/// Example:
#[doc = docify::embed!("src/tests.rs", last_runtime_upgrade_spec_version_usage)]
pub fn last_runtime_upgrade_spec_version() -> u32 {
LastRuntimeUpgrade::<T>::get().map_or(0, |l| l.spec_version.0)
}

/// Returns true if the given account exists.
pub fn account_exists(who: &T::AccountId) -> bool {
Account::<T>::contains_key(who)
}
Expand Down
26 changes: 25 additions & 1 deletion substrate/frame/system/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::*;
use frame_support::{
assert_noop, assert_ok,
dispatch::{Pays, PostDispatchInfo, WithPostDispatchInfo},
traits::WhitelistedStorageKeys,
traits::{OnRuntimeUpgrade, WhitelistedStorageKeys},
};
use std::collections::BTreeSet;

Expand Down Expand Up @@ -773,3 +773,27 @@ pub fn from_actual_ref_time(ref_time: Option<u64>) -> PostDispatchInfo {
pub fn from_post_weight_info(ref_time: Option<u64>, pays_fee: Pays) -> PostDispatchInfo {
PostDispatchInfo { actual_weight: ref_time.map(|t| Weight::from_all(t)), pays_fee }
}

#[docify::export]
#[test]
fn last_runtime_upgrade_spec_version_usage() {
struct Migration;

impl OnRuntimeUpgrade for Migration {
fn on_runtime_upgrade() -> Weight {
// Ensure to compare the spec version against some static version to prevent applying
// the same migration multiple times.
//
// `1337` here is the spec version of the runtime running on chain. If there is maybe
// a runtime upgrade in the pipeline of being applied, you should use the spec version
// of this upgrade.
if System::last_runtime_upgrade_spec_version() > 1337 {
return Weight::zero();
}

// Do the migration.

Weight::zero()
}
}
}