Refactoring Checkpoint: (WIP)

This commit is contained in:
2025-12-14 10:29:31 +03:00
parent 6588d9a1f2
commit 0c5d19e3a0
1423 changed files with 6413 additions and 6062 deletions
@@ -0,0 +1,108 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Benchmarking for the `pezcumulus-pezpallet-dmp-queue`.
#![cfg(feature = "runtime-benchmarks")]
use crate::*;
use alloc::vec;
use pezframe_benchmarking::v2::*;
use pezframe_support::{pezpallet_prelude::*, traits::Hooks};
#[benchmarks]
mod benchmarks {
use super::*;
/// This benchmark uses the proper maximal message length.
#[benchmark]
fn on_idle_good_msg() {
let msg = vec![123; MaxDmpMessageLenOf::<T>::get() as usize];
Pages::<T>::insert(0, vec![(123, msg.clone())]);
PageIndex::<T>::put(PageIndexData { begin_used: 0, end_used: 1, overweight_count: 0 });
MigrationStatus::<T>::set(MigrationState::StartedExport { next_begin_used: 0 });
#[block]
{
Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
}
assert_last_event::<T>(Event::Exported { page: 0 }.into());
}
/// This benchmark uses 64 KiB messages to emulate a large old message.
#[benchmark]
fn on_idle_large_msg() {
let msg = vec![123; 1 << 16];
Pages::<T>::insert(0, vec![(123, msg.clone())]);
PageIndex::<T>::put(PageIndexData { begin_used: 0, end_used: 1, overweight_count: 0 });
MigrationStatus::<T>::set(MigrationState::StartedExport { next_begin_used: 0 });
#[block]
{
Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
}
assert_last_event::<T>(Event::Exported { page: 0 }.into());
}
#[benchmark]
fn on_idle_overweight_good_msg() {
let msg = vec![123; MaxDmpMessageLenOf::<T>::get() as usize];
Overweight::<T>::insert(0, (123, msg.clone()));
PageIndex::<T>::put(PageIndexData { begin_used: 0, end_used: 1, overweight_count: 1 });
MigrationStatus::<T>::set(MigrationState::StartedOverweightExport {
next_overweight_index: 0,
});
#[block]
{
Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
}
assert_last_event::<T>(Event::ExportedOverweight { index: 0 }.into());
}
#[benchmark]
fn on_idle_overweight_large_msg() {
let msg = vec![123; 1 << 16];
Overweight::<T>::insert(0, (123, msg.clone()));
PageIndex::<T>::put(PageIndexData { begin_used: 0, end_used: 1, overweight_count: 1 });
MigrationStatus::<T>::set(MigrationState::StartedOverweightExport {
next_overweight_index: 0,
});
#[block]
{
Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
}
assert_last_event::<T>(Event::ExportOverweightFailed { index: 0 }.into());
}
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Runtime);
}
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
let events = pezframe_system::Pallet::<T>::events();
let system_event: <T as pezframe_system::Config>::RuntimeEvent = generic_event.into();
let pezframe_system::EventRecord { event, .. } = events.last().expect("Event expected");
assert_eq!(event, &system_event.into());
}
+291
View File
@@ -0,0 +1,291 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This pallet used to implement a message queue for downward messages from the relay-chain.
//!
//! It is now deprecated and has been refactored to simply drain any remaining messages into
//! something implementing `HandleMessage`. It proceeds in the state of
//! [`MigrationState`] one by one by their listing in the source code. The pallet can be removed
//! from the runtime once `Completed` was emitted.
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(deprecated)] // The pallet itself is deprecated.
extern crate alloc;
use migration::*;
pub use pallet::*;
mod benchmarking;
mod migration;
mod mock;
mod tests;
pub mod weights;
pub use weights::WeightInfo;
/// The maximal length of a DMP message.
pub type MaxDmpMessageLenOf<T> =
<<T as Config>::DmpSink as pezframe_support::traits::HandleMessage>::MaxMessageLen;
#[pezframe_support::pallet]
#[deprecated(
note = "`pezcumulus-pezpallet-dmp-queue` will be removed after November 2024. It can be removed once its lazy migration completed. See <https://github.com/pezkuwichain/kurdistan-sdk/issues/101>."
)]
pub mod pallet {
use super::*;
use pezframe_support::{pezpallet_prelude::*, traits::HandleMessage, weights::WeightMeter};
use pezframe_system::pezpallet_prelude::*;
use pezsp_io::hashing::twox_128;
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: pezframe_system::Config {
/// The overarching event type of the runtime.
#[allow(deprecated)]
type RuntimeEvent: From<Event<Self>> + IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
/// The sink for all DMP messages that the lazy migration will use.
type DmpSink: HandleMessage;
/// Weight info for this pallet (only needed for the lazy migration).
type WeightInfo: WeightInfo;
}
/// The migration state of this pallet.
#[pallet::storage]
pub type MigrationStatus<T> = StorageValue<_, MigrationState, ValueQuery>;
/// The lazy-migration state of the pallet.
#[derive(
codec::Encode, codec::Decode, Debug, PartialEq, Eq, Clone, MaxEncodedLen, TypeInfo,
)]
pub enum MigrationState {
/// Migration has not started yet.
NotStarted,
/// The export of pages started.
StartedExport {
/// The next page that should be exported.
next_begin_used: PageCounter,
},
/// The page export completed.
CompletedExport,
/// The export of overweight messages started.
StartedOverweightExport {
/// The next overweight index that should be exported.
next_overweight_index: u64,
},
/// The export of overweight messages completed.
CompletedOverweightExport,
/// The storage cleanup started.
StartedCleanup { cursor: Option<BoundedVec<u8, ConstU32<1024>>> },
/// The migration finished. The pallet can now be removed from the runtime.
Completed,
}
impl Default for MigrationState {
fn default() -> Self {
Self::NotStarted
}
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// The export of pages started.
StartedExport,
/// The export of a page completed.
Exported { page: PageCounter },
/// The export of a page failed.
///
/// This should never be emitted.
ExportFailed { page: PageCounter },
/// The export of pages completed.
CompletedExport,
/// The export of overweight messages started.
StartedOverweightExport,
/// The export of an overweight message completed.
ExportedOverweight { index: OverweightIndex },
/// The export of an overweight message failed.
///
/// This should never be emitted.
ExportOverweightFailed { index: OverweightIndex },
/// The export of overweight messages completed.
CompletedOverweightExport,
/// The cleanup of remaining pallet storage started.
StartedCleanup,
/// Some debris was cleaned up.
CleanedSome { keys_removed: u32 },
/// The cleanup of remaining pallet storage completed.
Completed { error: bool },
}
#[pallet::call]
impl<T: Config> Pallet<T> {}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn integrity_test() {
let w = Self::on_idle_weight();
assert!(w != Weight::zero());
assert!(w.all_lte(T::BlockWeights::get().max_block));
}
fn on_idle(now: BlockNumberFor<T>, limit: Weight) -> Weight {
let mut meter = WeightMeter::with_limit(limit);
if meter.try_consume(Self::on_idle_weight()).is_err() {
log::debug!(target: LOG, "Not enough weight for on_idle. {} < {}", Self::on_idle_weight(), limit);
return meter.consumed();
}
let state = MigrationStatus::<T>::get();
let index = PageIndex::<T>::get();
log::debug!(target: LOG, "on_idle: block={:?}, state={:?}, index={:?}", now, state, index);
match state {
MigrationState::NotStarted => {
log::debug!(target: LOG, "Init export at page {}", index.begin_used);
MigrationStatus::<T>::put(MigrationState::StartedExport {
next_begin_used: index.begin_used,
});
Self::deposit_event(Event::StartedExport);
},
MigrationState::StartedExport { next_begin_used } => {
log::debug!(target: LOG, "Exporting page {}", next_begin_used);
if next_begin_used == index.end_used {
MigrationStatus::<T>::put(MigrationState::CompletedExport);
log::debug!(target: LOG, "CompletedExport");
Self::deposit_event(Event::CompletedExport);
} else {
let res = migration::migrate_page::<T>(next_begin_used);
MigrationStatus::<T>::put(MigrationState::StartedExport {
next_begin_used: next_begin_used.saturating_add(1),
});
if let Ok(()) = res {
log::debug!(target: LOG, "Exported page {}", next_begin_used);
Self::deposit_event(Event::Exported { page: next_begin_used });
} else {
Self::deposit_event(Event::ExportFailed { page: next_begin_used });
}
}
},
MigrationState::CompletedExport => {
log::debug!(target: LOG, "Init export overweight at index 0");
MigrationStatus::<T>::put(MigrationState::StartedOverweightExport {
next_overweight_index: 0,
});
Self::deposit_event(Event::StartedOverweightExport);
},
MigrationState::StartedOverweightExport { next_overweight_index } => {
log::debug!(target: LOG, "Exporting overweight index {}", next_overweight_index);
if next_overweight_index == index.overweight_count {
MigrationStatus::<T>::put(MigrationState::CompletedOverweightExport);
log::debug!(target: LOG, "CompletedOverweightExport");
Self::deposit_event(Event::CompletedOverweightExport);
} else {
let res = migration::migrate_overweight::<T>(next_overweight_index);
MigrationStatus::<T>::put(MigrationState::StartedOverweightExport {
next_overweight_index: next_overweight_index.saturating_add(1),
});
if let Ok(()) = res {
log::debug!(target: LOG, "Exported overweight index {next_overweight_index}");
Self::deposit_event(Event::ExportedOverweight {
index: next_overweight_index,
});
} else {
Self::deposit_event(Event::ExportOverweightFailed {
index: next_overweight_index,
});
}
}
},
MigrationState::CompletedOverweightExport => {
log::debug!(target: LOG, "Init cleanup");
MigrationStatus::<T>::put(MigrationState::StartedCleanup { cursor: None });
Self::deposit_event(Event::StartedCleanup);
},
MigrationState::StartedCleanup { cursor } => {
log::debug!(target: LOG, "Cleaning up");
let hashed_prefix =
twox_128(<Pallet<T> as PalletInfoAccess>::name().as_bytes());
let result = pezframe_support::storage::unhashed::clear_prefix(
&hashed_prefix,
Some(2), // Somehow it does nothing when set to 1, so we set it to 2.
cursor.as_ref().map(|c| c.as_ref()),
);
Self::deposit_event(Event::CleanedSome { keys_removed: result.backend });
// GOTCHA! We deleted *all* pallet storage; hence we also our own
// `MigrationState`. BUT we insert it back:
if let Some(unbound_cursor) = result.maybe_cursor {
if let Ok(cursor) = unbound_cursor.try_into() {
log::debug!(target: LOG, "Next cursor: {:?}", &cursor);
MigrationStatus::<T>::put(MigrationState::StartedCleanup {
cursor: Some(cursor),
});
} else {
MigrationStatus::<T>::put(MigrationState::Completed);
log::error!(target: LOG, "Completed with error: could not bound cursor");
Self::deposit_event(Event::Completed { error: true });
}
} else {
MigrationStatus::<T>::put(MigrationState::Completed);
log::debug!(target: LOG, "Completed");
Self::deposit_event(Event::Completed { error: false });
}
},
MigrationState::Completed => {
log::debug!(target: LOG, "Idle; you can remove this pallet");
},
}
meter.consumed()
}
}
impl<T: Config> Pallet<T> {
/// The worst-case weight of [`Self::on_idle`].
pub fn on_idle_weight() -> Weight {
<T as crate::Config>::WeightInfo::on_idle_good_msg()
.max(<T as crate::Config>::WeightInfo::on_idle_large_msg())
}
}
}
@@ -0,0 +1,113 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezcumulus.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Migrates the storage from the previously deleted DMP pallet.
use crate::*;
use alloc::vec::Vec;
use pezcumulus_primitives_core::relay_chain::BlockNumber as RelayBlockNumber;
use pezframe_support::{pezpallet_prelude::*, storage_alias, traits::HandleMessage};
pub(crate) const LOG: &str = "runtime::dmp-queue-export-xcms";
/// The old `PageIndexData` struct.
#[derive(Copy, Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct PageIndexData {
/// The lowest used page index.
pub begin_used: PageCounter,
/// The lowest unused page index.
pub end_used: PageCounter,
/// The number of overweight messages ever recorded (and thus the lowest free index).
pub overweight_count: OverweightIndex,
}
/// The old `MigrationState` type.
pub type OverweightIndex = u64;
/// The old `MigrationState` type.
pub type PageCounter = u32;
/// The old `PageIndex` storage item.
#[storage_alias]
pub type PageIndex<T: Config> = StorageValue<Pallet<T>, PageIndexData, ValueQuery>;
/// The old `Pages` storage item.
#[storage_alias]
pub type Pages<T: Config> = StorageMap<
Pallet<T>,
Blake2_128Concat,
PageCounter,
Vec<(RelayBlockNumber, Vec<u8>)>,
ValueQuery,
>;
/// The old `Overweight` storage item.
#[storage_alias]
pub type Overweight<T: Config> = CountedStorageMap<
Pallet<T>,
Blake2_128Concat,
OverweightIndex,
(RelayBlockNumber, Vec<u8>),
OptionQuery,
>;
pub(crate) mod testing_only {
use super::*;
/// This alias is not used by the migration but only for testing.
///
/// Note that the alias type is wrong on purpose.
#[storage_alias]
pub type Configuration<T: Config> = StorageValue<Pallet<T>, u32>;
}
/// Migrates a single page to the `DmpSink`.
pub(crate) fn migrate_page<T: crate::Config>(p: PageCounter) -> Result<(), ()> {
let page = Pages::<T>::take(p);
log::debug!(target: LOG, "Migrating page #{p} with {} messages ...", page.len());
if page.is_empty() {
log::error!(target: LOG, "Page #{p}: EMPTY - storage corrupted?");
return Err(());
}
for (m, (block, msg)) in page.iter().enumerate() {
let Ok(bound) = BoundedVec::<u8, _>::try_from(msg.clone()) else {
log::error!(target: LOG, "[Page {p}] Message #{m}: TOO LONG - dropping");
continue;
};
T::DmpSink::handle_message(bound.as_bounded_slice());
log::debug!(target: LOG, "[Page {p}] Migrated message #{m} from block {block}");
}
Ok(())
}
/// Migrates a single overweight message to the `DmpSink`.
pub(crate) fn migrate_overweight<T: crate::Config>(i: OverweightIndex) -> Result<(), ()> {
let Some((block, msg)) = Overweight::<T>::take(i) else {
log::error!(target: LOG, "[Overweight {i}] Message: EMPTY - storage corrupted?");
return Err(());
};
let Ok(bound) = BoundedVec::<u8, _>::try_from(msg) else {
log::error!(target: LOG, "[Overweight {i}] Message: TOO LONG - dropping");
return Err(());
};
T::DmpSink::handle_message(bound.as_bounded_slice());
log::debug!(target: LOG, "[Overweight {i}] Migrated message from block {block}");
Ok(())
}
@@ -0,0 +1,76 @@
// This file is part of Pezcumulus.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg(test)]
use pezframe_support::{derive_impl, parameter_types, traits::HandleMessage};
use pezsp_core::{bounded_vec::BoundedSlice, ConstU32};
use pezsp_runtime::traits::IdentityLookup;
type Block = pezframe_system::mocking::MockBlock<Runtime>;
// Configure a mock runtime to test the pallet.
pezframe_support::construct_runtime!(
pub enum Runtime
{
System: pezframe_system,
DmpQueue: crate,
}
);
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
impl pezframe_system::Config for Runtime {
type Block = Block;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Lookup = IdentityLookup<Self::AccountId>;
type RuntimeEvent = RuntimeEvent;
type PalletInfo = PalletInfo;
}
impl crate::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type DmpSink = RecordingDmpSink;
type WeightInfo = ();
}
parameter_types! {
/// All messages that came into the `DmpSink`.
pub static RecordedMessages: Vec<Vec<u8>> = vec![];
}
/// Can be used as [`Config::DmpSink`] to record all messages that came in.
pub struct RecordingDmpSink;
impl HandleMessage for RecordingDmpSink {
type MaxMessageLen = ConstU32<16>;
fn handle_message(msg: BoundedSlice<u8, Self::MaxMessageLen>) {
RecordedMessages::mutate(|n| n.push(msg.to_vec()));
}
fn handle_messages<'a>(_: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>) {
unimplemented!()
}
fn sweep_queue() {
unimplemented!()
}
}
pub fn new_test_ext() -> pezsp_io::TestExternalities {
pezsp_io::TestExternalities::new(Default::default())
}
@@ -0,0 +1,228 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezcumulus.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Test the lazy migration.
#![cfg(test)]
use super::{migration::*, mock::*};
use crate::*;
use pezframe_support::{pezpallet_prelude::*, traits::OnIdle, StorageNoopGuard};
#[test]
fn migration_works() {
let mut ext = new_test_ext();
ext.execute_with(|| {
pezsp_tracing::try_init_simple();
// Insert some storage:
PageIndex::<Runtime>::set(PageIndexData {
begin_used: 10,
end_used: 20,
overweight_count: 5,
});
for p in 10..20 {
let msgs = (0..16).map(|i| (p, vec![i as u8; 1])).collect::<Vec<_>>();
Pages::<Runtime>::insert(p, msgs);
}
for i in 0..5 {
Overweight::<Runtime>::insert(i, (0, vec![i as u8; 1]));
}
testing_only::Configuration::<Runtime>::put(123);
});
// We need to commit, otherwise the keys are removed from the overlay; not the backend.
ext.commit_all().unwrap();
ext.execute_with(|| {
// Run one step of the migration:
pre_upgrade_checks::<Runtime>();
run_to_block(1);
// First we expect a StartedExport event:
assert_only_event(Event::StartedExport);
// Then we expect 10 Exported events:
for page in 0..10 {
run_to_block(2 + page);
assert_only_event(Event::Exported { page: page as u32 + 10 });
assert!(!Pages::<Runtime>::contains_key(page as u32), "Page is gone");
assert_eq!(
MigrationStatus::<Runtime>::get(),
MigrationState::StartedExport { next_begin_used: page as u32 + 11 }
);
}
// Then we expect a CompletedExport event:
run_to_block(12);
assert_only_event(Event::CompletedExport);
assert_eq!(MigrationStatus::<Runtime>::get(), MigrationState::CompletedExport);
// Then we expect a StartedOverweightExport event:
run_to_block(13);
assert_only_event(Event::StartedOverweightExport);
assert_eq!(
MigrationStatus::<Runtime>::get(),
MigrationState::StartedOverweightExport { next_overweight_index: 0 }
);
// Then we expect 5 ExportedOverweight events:
for index in 0..5 {
run_to_block(14 + index);
assert_only_event(Event::ExportedOverweight { index });
assert!(!Overweight::<Runtime>::contains_key(index), "Overweight msg is gone");
assert_eq!(
MigrationStatus::<Runtime>::get(),
MigrationState::StartedOverweightExport { next_overweight_index: index + 1 }
);
}
// Then we expect a CompletedOverweightExport event:
run_to_block(19);
assert_only_event(Event::CompletedOverweightExport);
assert_eq!(MigrationStatus::<Runtime>::get(), MigrationState::CompletedOverweightExport);
// Then we expect a StartedCleanup event:
run_to_block(20);
assert_only_event(Event::StartedCleanup);
assert_eq!(
MigrationStatus::<Runtime>::get(),
MigrationState::StartedCleanup { cursor: None }
);
});
ext.commit_all().unwrap();
// Then it cleans up the remaining storage items:
ext.execute_with(|| {
run_to_block(21);
assert_only_event(Event::CleanedSome { keys_removed: 2 });
});
ext.commit_all().unwrap();
ext.execute_with(|| {
run_to_block(22);
assert_only_event(Event::CleanedSome { keys_removed: 2 });
});
ext.commit_all().unwrap();
ext.execute_with(|| {
run_to_block(24);
assert_eq!(
System::events().into_iter().map(|e| e.event).collect::<Vec<_>>(),
vec![
Event::CleanedSome { keys_removed: 2 }.into(),
Event::Completed { error: false }.into()
]
);
System::reset_events();
assert_eq!(MigrationStatus::<Runtime>::get(), MigrationState::Completed);
post_upgrade_checks::<Runtime>();
assert_eq!(RecordedMessages::take().len(), 10 * 16 + 5);
// Test the storage removal:
assert!(!PageIndex::<Runtime>::exists());
assert!(!testing_only::Configuration::<Runtime>::exists());
assert_eq!(Pages::<Runtime>::iter_keys().count(), 0);
assert_eq!(Overweight::<Runtime>::iter_keys().count(), 0);
// The `MigrationStatus` never disappears and there are no more storage changes:
{
let _g = StorageNoopGuard::default();
run_to_block(100);
assert_eq!(MigrationStatus::<Runtime>::get(), MigrationState::Completed);
assert!(System::events().is_empty());
// ... besides the block number
System::set_block_number(24);
}
});
}
/// Too long messages are dropped by the migration.
#[test]
fn migration_too_long_ignored() {
new_test_ext().execute_with(|| {
// Setup the storage:
PageIndex::<Runtime>::set(PageIndexData {
begin_used: 10,
end_used: 11,
overweight_count: 2,
});
let short = vec![1; 16];
let long = vec![0; 17];
Pages::<Runtime>::insert(10, vec![(10, short.clone()), (10, long.clone())]);
// Insert one good and one bad overweight msg:
Overweight::<Runtime>::insert(0, (0, short.clone()));
Overweight::<Runtime>::insert(1, (0, long.clone()));
// Run the migration:
pre_upgrade_checks::<Runtime>();
run_to_block(100);
post_upgrade_checks::<Runtime>();
assert_eq!(RecordedMessages::take(), vec![short.clone(), short]);
// Test the storage removal:
assert!(!PageIndex::<Runtime>::exists());
assert_eq!(Pages::<Runtime>::iter_keys().count(), 0);
assert_eq!(Overweight::<Runtime>::iter_keys().count(), 0);
});
}
fn run_to_block(n: u64) {
System::run_to_block_with::<AllPalletsWithSystem>(
n,
pezframe_system::RunToBlockHooks::default().after_initialize(|bn| {
AllPalletsWithSystem::on_idle(bn, Weight::MAX);
}),
);
}
fn assert_only_event(e: Event<Runtime>) {
assert_eq!(System::events().pop().expect("Event expected").event, e.clone().into());
assert_eq!(System::events().len(), 1, "Got events: {:?} but wanted {:?}", System::events(), e);
System::reset_events();
}
/// TESTING ONLY
fn pre_upgrade_checks<T: crate::Config>() {
let index = PageIndex::<T>::get();
// Check that all pages are present.
assert!(index.begin_used <= index.end_used, "Invalid page index");
for p in index.begin_used..index.end_used {
assert!(Pages::<T>::contains_key(p), "Missing page");
assert!(Pages::<T>::get(p).len() > 0, "Empty page");
}
// Check that all overweight messages are present.
for i in 0..index.overweight_count {
assert!(Overweight::<T>::contains_key(i), "Missing overweight message");
}
}
/// TESTING ONLY
fn post_upgrade_checks<T: crate::Config>() {
let index = PageIndex::<T>::get();
// Check that all pages are removed.
for p in index.begin_used..index.end_used {
assert!(!Pages::<T>::contains_key(p), "Page should be gone");
}
assert!(Pages::<T>::iter_keys().next().is_none(), "Un-indexed pages");
// Check that all overweight messages are removed.
for i in 0..index.overweight_count {
assert!(!Overweight::<T>::contains_key(i), "Overweight message should be gone");
}
assert!(Overweight::<T>::iter_keys().next().is_none(), "Un-indexed overweight messages");
}
@@ -0,0 +1,222 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Autogenerated weights for `pezcumulus_pezpallet_dmp_queue`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `Olivers-MacBook-Pro.local`, CPU: `<UNKNOWN>`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-kusama-dev")`, DB CACHE: `1024`
// Executed Command:
// ./target/release/pezkuwi-teyrchain
// benchmark
// pallet
// --pallet
// pezcumulus-pezpallet-dmp-queue
// --chain
// asset-hub-kusama-dev
// --output
// pezcumulus/pezpallets/dmp-queue/src/weights.rs
// --template
// bizinikiwi/.maintain/frame-weight-template.hbs
// --extrinsic
//
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use core::marker::PhantomData;
/// Weight functions needed for `pezcumulus_pezpallet_dmp_queue`.
pub trait WeightInfo {
fn on_idle_good_msg() -> Weight;
fn on_idle_large_msg() -> Weight;
fn on_idle_overweight_good_msg() -> Weight;
fn on_idle_overweight_large_msg() -> Weight;
}
/// Weights for `pezcumulus_pezpallet_dmp_queue` using the Bizinikiwi node and recommended hardware.
pub struct BizinikiwiWeight<T>(PhantomData<T>);
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::ServiceHead` (r:1 w:1)
/// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::Pages` (r:0 w:1)
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65585), added: 68060, mode: `MaxEncodedLen`)
fn on_idle_good_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65696`
// Estimated: `69161`
// Minimum execution time: 124_651_000 picoseconds.
Weight::from_parts(127_857_000, 0)
.saturating_add(Weight::from_parts(0, 69161))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(5))
}
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
fn on_idle_large_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65659`
// Estimated: `69124`
// Minimum execution time: 65_684_000 picoseconds.
Weight::from_parts(68_039_000, 0)
.saturating_add(Weight::from_parts(0, 69124))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::ServiceHead` (r:1 w:1)
/// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::Pages` (r:0 w:1)
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65585), added: 68060, mode: `MaxEncodedLen`)
fn on_idle_overweight_good_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65726`
// Estimated: `69191`
// Minimum execution time: 117_657_000 picoseconds.
Weight::from_parts(122_035_000, 0)
.saturating_add(Weight::from_parts(0, 69191))
.saturating_add(T::DbWeight::get().reads(6))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
fn on_idle_overweight_large_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65689`
// Estimated: `69154`
// Minimum execution time: 59_799_000 picoseconds.
Weight::from_parts(61_354_000, 0)
.saturating_add(Weight::from_parts(0, 69154))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(3))
}
}
// For backwards compatibility and tests.
impl WeightInfo for () {
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::ServiceHead` (r:1 w:1)
/// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::Pages` (r:0 w:1)
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65585), added: 68060, mode: `MaxEncodedLen`)
fn on_idle_good_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65696`
// Estimated: `69161`
// Minimum execution time: 124_651_000 picoseconds.
Weight::from_parts(127_857_000, 0)
.saturating_add(Weight::from_parts(0, 69161))
.saturating_add(RocksDbWeight::get().reads(5))
.saturating_add(RocksDbWeight::get().writes(5))
}
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca7d95d3e948effbeccff2de2c182672836` (r:1 w:1)
fn on_idle_large_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65659`
// Estimated: `69124`
// Minimum execution time: 65_684_000 picoseconds.
Weight::from_parts(68_039_000, 0)
.saturating_add(Weight::from_parts(0, 69124))
.saturating_add(RocksDbWeight::get().reads(3))
.saturating_add(RocksDbWeight::get().writes(2))
}
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::ServiceHead` (r:1 w:1)
/// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
/// Storage: `MessageQueue::Pages` (r:0 w:1)
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65585), added: 68060, mode: `MaxEncodedLen`)
fn on_idle_overweight_good_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65726`
// Estimated: `69191`
// Minimum execution time: 117_657_000 picoseconds.
Weight::from_parts(122_035_000, 0)
.saturating_add(Weight::from_parts(0, 69191))
.saturating_add(RocksDbWeight::get().reads(6))
.saturating_add(RocksDbWeight::get().writes(6))
}
/// Storage: `DmpQueue::MigrationStatus` (r:1 w:1)
/// Proof: `DmpQueue::MigrationStatus` (`max_values`: Some(1), `max_size`: Some(1028), added: 1523, mode: `MaxEncodedLen`)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca754904d6d8c6fe06c4e5965f9b8397421` (r:1 w:0)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca70f923ef3252d0166429d36d20ed665a8` (r:1 w:1)
/// Storage: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
/// Proof: UNKNOWN KEY `0xcd5c1f6df63bc97f4a8ce37f14a50ca772275f64c354954352b71eea39cfaca2` (r:1 w:1)
fn on_idle_overweight_large_msg() -> Weight {
// Proof Size summary in bytes:
// Measured: `65689`
// Estimated: `69154`
// Minimum execution time: 59_799_000 picoseconds.
Weight::from_parts(61_354_000, 0)
.saturating_add(Weight::from_parts(0, 69154))
.saturating_add(RocksDbWeight::get().reads(4))
.saturating_add(RocksDbWeight::get().writes(3))
}
}