Refactoring Checkpoint: (WIP)
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
// 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 setup for pezcumulus-pezpallet-xcmp-queue
|
||||
|
||||
use crate::{weights_ext::get_average_page_pos, *};
|
||||
|
||||
use alloc::vec;
|
||||
use codec::DecodeAll;
|
||||
use pezframe_benchmarking::v2::*;
|
||||
use pezframe_support::{assert_ok, traits::Hooks};
|
||||
use pezframe_system::RawOrigin;
|
||||
use xcm::MAX_INSTRUCTIONS_TO_DECODE;
|
||||
|
||||
#[benchmarks]
|
||||
mod benchmarks {
|
||||
use super::*;
|
||||
|
||||
/// Modify any of the `QueueConfig` fields with a new `u32` value.
|
||||
///
|
||||
/// Used as weight for:
|
||||
/// - update_suspend_threshold
|
||||
/// - update_drop_threshold
|
||||
/// - update_resume_threshold
|
||||
#[benchmark]
|
||||
fn set_config_with_u32() {
|
||||
#[extrinsic_call]
|
||||
Pallet::<T>::update_resume_threshold(RawOrigin::Root, 1);
|
||||
}
|
||||
|
||||
/// Add a XCMP message of `n` bytes to the message queue.
|
||||
///
|
||||
/// The message will be added on a new page and also, the `BookState` will be added
|
||||
/// to the ready ring.
|
||||
#[benchmark]
|
||||
fn enqueue_n_bytes_xcmp_message(n: Linear<0, { MaxXcmpMessageLenOf::<T>::get() }>) {
|
||||
#[cfg(test)]
|
||||
{
|
||||
mock::EnqueuedMessages::set(vec![]);
|
||||
}
|
||||
|
||||
let msg = BoundedVec::try_from(vec![0; n as usize]).unwrap();
|
||||
|
||||
#[cfg(not(test))]
|
||||
let fp_before = T::XcmpQueue::footprint(0.into());
|
||||
#[block]
|
||||
{
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&[msg.as_bounded_slice()],
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let fp_after = T::XcmpQueue::footprint(0.into());
|
||||
assert_eq!(fp_after.ready_pages, fp_before.ready_pages + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add `n` XCMP message of 0 bytes to the message queue.
|
||||
///
|
||||
/// Only for the first message a new page will be created and the `BookState` will be added
|
||||
/// to the ready ring.
|
||||
#[benchmark]
|
||||
fn enqueue_n_empty_xcmp_messages(n: Linear<0, 1000>) {
|
||||
#[cfg(test)]
|
||||
{
|
||||
mock::EnqueuedMessages::set(vec![]);
|
||||
<QueueConfig<T>>::set(QueueConfigData {
|
||||
suspend_threshold: 1100,
|
||||
drop_threshold: 1100,
|
||||
resume_threshold: 1100,
|
||||
});
|
||||
}
|
||||
|
||||
let msg = BoundedVec::new();
|
||||
let msgs = vec![msg.as_bounded_slice(); n as usize];
|
||||
|
||||
#[cfg(not(test))]
|
||||
let fp_before = T::XcmpQueue::footprint(0.into());
|
||||
#[block]
|
||||
{
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&msgs,
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let fp_after = T::XcmpQueue::footprint(0.into());
|
||||
if !msgs.is_empty() {
|
||||
assert_eq!(fp_after.ready_pages, fp_before.ready_pages + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add an XCMP message of 0 bytes to the message queue at the provided position
|
||||
/// on an existing page.
|
||||
#[benchmark(pov_mode = Measured)]
|
||||
fn enqueue_empty_xcmp_message_at(
|
||||
n: Linear<0, { crate::MaxXcmpMessageLenOf::<T>::get() - 10 }>,
|
||||
) {
|
||||
#[cfg(test)]
|
||||
{
|
||||
mock::EnqueuedMessages::set(vec![]);
|
||||
}
|
||||
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&[BoundedVec::try_from(vec![0; n as usize]).unwrap().as_bounded_slice()],
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
|
||||
#[cfg(not(test))]
|
||||
let fp_before = T::XcmpQueue::footprint(0.into());
|
||||
#[block]
|
||||
{
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&[BoundedVec::new().as_bounded_slice()],
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let fp_after = T::XcmpQueue::footprint(0.into());
|
||||
assert_eq!(fp_after.ready_pages, fp_before.ready_pages);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add `n` pages to the message queue.
|
||||
///
|
||||
/// We add one page by enqueueing a maximal size message which fills it.
|
||||
#[benchmark]
|
||||
fn enqueue_n_full_pages(n: Linear<0, 100>) {
|
||||
#[cfg(test)]
|
||||
{
|
||||
mock::EnqueuedMessages::set(vec![]);
|
||||
}
|
||||
<QueueConfig<T>>::set(QueueConfigData {
|
||||
suspend_threshold: 200,
|
||||
drop_threshold: 200,
|
||||
resume_threshold: 200,
|
||||
});
|
||||
|
||||
let max_msg_len = MaxXcmpMessageLenOf::<T>::get() as usize;
|
||||
let mut msgs = vec![];
|
||||
for _i in 0..n {
|
||||
let msg = BoundedVec::try_from(vec![0; max_msg_len]).unwrap();
|
||||
msgs.push(msg);
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
let fp_before = T::XcmpQueue::footprint(0.into());
|
||||
#[block]
|
||||
{
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&msgs.iter().map(|msg| msg.as_bounded_slice()).collect::<Vec<_>>(),
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let fp_after = T::XcmpQueue::footprint(0.into());
|
||||
assert_eq!(fp_after.ready_pages, fp_before.ready_pages + n);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark(pov_mode = Measured)]
|
||||
fn enqueue_1000_small_xcmp_messages() {
|
||||
#[cfg(test)]
|
||||
{
|
||||
<QueueConfig<T>>::set(QueueConfigData {
|
||||
suspend_threshold: 1100,
|
||||
drop_threshold: 1100,
|
||||
resume_threshold: 1100,
|
||||
});
|
||||
}
|
||||
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&[BoundedVec::try_from(vec![
|
||||
0;
|
||||
get_average_page_pos(MaxXcmpMessageLenOf::<T>::get())
|
||||
as usize
|
||||
])
|
||||
.unwrap()
|
||||
.as_bounded_slice()],
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
|
||||
let mut msgs = vec![];
|
||||
for _i in 0..1000 {
|
||||
msgs.push(BoundedVec::try_from(vec![0; 3]).unwrap());
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
let fp_before = T::XcmpQueue::footprint(0.into());
|
||||
#[block]
|
||||
{
|
||||
assert_ok!(Pallet::<T>::enqueue_xcmp_messages(
|
||||
0.into(),
|
||||
&msgs.iter().map(|msg| msg.as_bounded_slice()).collect::<Vec<_>>(),
|
||||
true,
|
||||
&mut WeightMeter::new()
|
||||
));
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let fp_after = T::XcmpQueue::footprint(0.into());
|
||||
assert_eq!(fp_after.ready_pages, fp_before.ready_pages);
|
||||
}
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn suspend_channel() {
|
||||
let para = 123.into();
|
||||
let data = ChannelSignal::Suspend.encode();
|
||||
|
||||
#[block]
|
||||
{
|
||||
ChannelSignal::decode_all(&mut &data[..]).unwrap();
|
||||
Pallet::<T>::suspend_channel(para);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
OutboundXcmpStatus::<T>::get()
|
||||
.iter()
|
||||
.find(|p| p.recipient == para)
|
||||
.unwrap()
|
||||
.state,
|
||||
OutboundState::Suspended
|
||||
);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn resume_channel() {
|
||||
let para = 123.into();
|
||||
let data = ChannelSignal::Resume.encode();
|
||||
|
||||
Pallet::<T>::suspend_channel(para);
|
||||
|
||||
#[block]
|
||||
{
|
||||
ChannelSignal::decode_all(&mut &data[..]).unwrap();
|
||||
Pallet::<T>::resume_channel(para);
|
||||
}
|
||||
|
||||
assert!(
|
||||
OutboundXcmpStatus::<T>::get().iter().all(|p| p.recipient != para),
|
||||
"No messages in the channel; therefore removed."
|
||||
);
|
||||
}
|
||||
|
||||
/// Split a singular XCM.
|
||||
#[benchmark]
|
||||
fn take_first_concatenated_xcm(
|
||||
n: Linear<0, { MAX_INSTRUCTIONS_TO_DECODE as u32 - MAX_XCM_DECODE_DEPTH }>,
|
||||
) {
|
||||
let mut xcm = Xcm::<T>(vec![ClearOrigin; n as usize]);
|
||||
for _ in 0..MAX_XCM_DECODE_DEPTH - 1 {
|
||||
xcm = Xcm::<T>(vec![Instruction::SetAppendix(xcm)]);
|
||||
}
|
||||
let data = VersionedXcm::<T>::from(xcm).encode();
|
||||
|
||||
#[block]
|
||||
{
|
||||
Pallet::<T>::take_first_concatenated_xcm(&mut &data[..], &mut WeightMeter::new())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Benchmark the migration for a maximal sized message.
|
||||
#[benchmark]
|
||||
fn on_idle_good_msg() {
|
||||
use migration::v3;
|
||||
|
||||
let block = 5;
|
||||
let para = ParaId::from(4);
|
||||
let message = vec![123u8; MaxXcmpMessageLenOf::<T>::get() as usize];
|
||||
let message_metadata = vec![(block, XcmpMessageFormat::ConcatenatedVersionedXcm)];
|
||||
|
||||
v3::InboundXcmpMessages::<T>::insert(para, block, message);
|
||||
v3::InboundXcmpStatus::<T>::set(Some(vec![v3::InboundChannelDetails {
|
||||
sender: para,
|
||||
state: v3::InboundState::Ok,
|
||||
message_metadata,
|
||||
}]));
|
||||
|
||||
#[block]
|
||||
{
|
||||
Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
/// Benchmark the migration with a 64 KiB message that will not be possible to enqueue.
|
||||
#[benchmark]
|
||||
fn on_idle_large_msg() {
|
||||
use migration::v3;
|
||||
|
||||
let block = 5;
|
||||
let para = ParaId::from(4);
|
||||
let message = vec![123u8; 1 << 16]; // 64 KiB message
|
||||
let message_metadata = vec![(block, XcmpMessageFormat::ConcatenatedVersionedXcm)];
|
||||
|
||||
v3::InboundXcmpMessages::<T>::insert(para, block, message);
|
||||
v3::InboundXcmpStatus::<T>::set(Some(vec![v3::InboundChannelDetails {
|
||||
sender: para,
|
||||
state: v3::InboundState::Ok,
|
||||
message_metadata,
|
||||
}]));
|
||||
|
||||
#[block]
|
||||
{
|
||||
Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// 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.
|
||||
|
||||
use crate::{pallet, OutboundState};
|
||||
use pezcumulus_primitives_core::ParaId;
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks
|
||||
/// both `OutboundXcmpStatus` and `InboundXcmpStatus` for defined `Location` if any of those is
|
||||
/// suspended.
|
||||
pub struct InAndOutXcmpChannelStatusProvider<Runtime>(core::marker::PhantomData<Runtime>);
|
||||
impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider
|
||||
for InAndOutXcmpChannelStatusProvider<Runtime>
|
||||
{
|
||||
fn is_congested(with: &Location) -> bool {
|
||||
// handle congestion only for a sibling teyrchain locations.
|
||||
let sibling_para_id: ParaId = match with.unpack() {
|
||||
(_, [Teyrchain(para_id)]) => (*para_id).into(),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
// if the inbound channel with recipient is suspended, it means that we are unable to
|
||||
// receive congestion reports from the `with` location. So we assume the pipeline is
|
||||
// congested too.
|
||||
if pallet::Pallet::<Runtime>::is_inbound_channel_suspended(sibling_para_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the outbound channel with recipient is suspended, it means that one of further
|
||||
// queues (e.g. bridge queue between two bridge hubs) is overloaded, so we shall
|
||||
// take larger fee for our outbound messages
|
||||
OutXcmpChannelStatusProvider::<Runtime>::is_congested(with)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adapter implementation for `bp_xcm_bridge::ChannelStatusProvider` and/or
|
||||
/// `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks only `OutboundXcmpStatus`
|
||||
/// for defined `Location` if is suspended.
|
||||
pub struct OutXcmpChannelStatusProvider<Runtime>(core::marker::PhantomData<Runtime>);
|
||||
impl<Runtime: crate::Config> OutXcmpChannelStatusProvider<Runtime> {
|
||||
fn is_congested(with: &Location) -> bool {
|
||||
// handle congestion only for a sibling teyrchain locations.
|
||||
let sibling_para_id: ParaId = match with.unpack() {
|
||||
(_, [Teyrchain(para_id)]) => (*para_id).into(),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
// let's find the channel's state with the sibling teyrchain,
|
||||
let Some((outbound_state, queued_pages)) =
|
||||
pallet::Pallet::<Runtime>::outbound_channel_state(sibling_para_id)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
// suspended channel => it is congested
|
||||
if outbound_state == OutboundState::Suspended {
|
||||
return true;
|
||||
}
|
||||
|
||||
// It takes some time for target teyrchain to suspend inbound channel with the target BH and
|
||||
// during that we will keep accepting new message delivery transactions. Let's also reject
|
||||
// new deliveries if there are too many "pages" (concatenated XCM messages) in the target BH
|
||||
// -> target teyrchain queue.
|
||||
|
||||
// If the outbound channel has at least `N` pages enqueued, let's assume it is congested.
|
||||
// Normally, the chain with a few opened HRMP channels, will "send" pages at every block.
|
||||
// Having `N` pages means that for last `N` blocks we either have not sent any messages,
|
||||
// or have sent signals.
|
||||
|
||||
const MAX_QUEUED_PAGES_BEFORE_DEACTIVATION: u16 = 4;
|
||||
if queued_pages > MAX_QUEUED_PAGES_BEFORE_DEACTIVATION {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider
|
||||
for OutXcmpChannelStatusProvider<Runtime>
|
||||
{
|
||||
fn is_congested(with: &Location) -> bool {
|
||||
Self::is_congested(with)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub fn suspend_channel_for_benchmarks<T: crate::Config>(target: ParaId) {
|
||||
pallet::Pallet::<T>::suspend_channel(target)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,427 @@
|
||||
// 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.
|
||||
|
||||
//! A module that is responsible for migration of storage.
|
||||
|
||||
pub mod v5;
|
||||
|
||||
use crate::{Config, OverweightIndex, Pallet, QueueConfig, QueueConfigData, DEFAULT_POV_SIZE};
|
||||
use alloc::vec::Vec;
|
||||
use pezcumulus_primitives_core::XcmpMessageFormat;
|
||||
use pezframe_support::{
|
||||
pezpallet_prelude::*,
|
||||
traits::{EnqueueMessage, StorageVersion, UncheckedOnRuntimeUpgrade},
|
||||
weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, Weight},
|
||||
};
|
||||
|
||||
/// The in-code storage version.
|
||||
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(5);
|
||||
|
||||
pub const LOG: &str = "runtime::xcmp-queue-migration";
|
||||
|
||||
mod v1 {
|
||||
use super::*;
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(crate) type QueueConfig<T: Config> = StorageValue<Pallet<T>, QueueConfigData, ValueQuery>;
|
||||
|
||||
#[derive(Encode, Decode, Debug)]
|
||||
pub struct QueueConfigData {
|
||||
pub suspend_threshold: u32,
|
||||
pub drop_threshold: u32,
|
||||
pub resume_threshold: u32,
|
||||
pub threshold_weight: u64,
|
||||
pub weight_restrict_decay: u64,
|
||||
pub xcmp_max_individual_weight: u64,
|
||||
}
|
||||
|
||||
impl Default for QueueConfigData {
|
||||
fn default() -> Self {
|
||||
QueueConfigData {
|
||||
suspend_threshold: 2,
|
||||
drop_threshold: 5,
|
||||
resume_threshold: 1,
|
||||
threshold_weight: 100_000,
|
||||
weight_restrict_decay: 2,
|
||||
xcmp_max_individual_weight: 20u64 * WEIGHT_REF_TIME_PER_MILLIS,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod v2 {
|
||||
use super::*;
|
||||
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(crate) type QueueConfig<T: Config> = StorageValue<Pallet<T>, QueueConfigData, ValueQuery>;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||
pub struct QueueConfigData {
|
||||
pub suspend_threshold: u32,
|
||||
pub drop_threshold: u32,
|
||||
pub resume_threshold: u32,
|
||||
pub threshold_weight: Weight,
|
||||
pub weight_restrict_decay: Weight,
|
||||
pub xcmp_max_individual_weight: Weight,
|
||||
}
|
||||
|
||||
impl Default for QueueConfigData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
suspend_threshold: 2,
|
||||
drop_threshold: 5,
|
||||
resume_threshold: 1,
|
||||
threshold_weight: Weight::from_parts(100_000, 0),
|
||||
weight_restrict_decay: Weight::from_parts(2, 0),
|
||||
xcmp_max_individual_weight: Weight::from_parts(
|
||||
20u64 * WEIGHT_REF_TIME_PER_MILLIS,
|
||||
DEFAULT_POV_SIZE,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Migrates `QueueConfigData` from v1 (using only reference time weights) to v2 (with
|
||||
/// 2D weights).
|
||||
pub struct UncheckedMigrationToV2<T: Config>(PhantomData<T>);
|
||||
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV2<T> {
|
||||
#[allow(deprecated)]
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let translate = |pre: v1::QueueConfigData| -> v2::QueueConfigData {
|
||||
v2::QueueConfigData {
|
||||
suspend_threshold: pre.suspend_threshold,
|
||||
drop_threshold: pre.drop_threshold,
|
||||
resume_threshold: pre.resume_threshold,
|
||||
threshold_weight: Weight::from_parts(pre.threshold_weight, 0),
|
||||
weight_restrict_decay: Weight::from_parts(pre.weight_restrict_decay, 0),
|
||||
xcmp_max_individual_weight: Weight::from_parts(
|
||||
pre.xcmp_max_individual_weight,
|
||||
DEFAULT_POV_SIZE,
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
if v2::QueueConfig::<T>::translate(|pre| pre.map(translate)).is_err() {
|
||||
tracing::error!(
|
||||
target: crate::LOG_TARGET,
|
||||
"unexpected error when performing translation of the QueueConfig type \
|
||||
during storage upgrade to v2"
|
||||
);
|
||||
}
|
||||
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// [`UncheckedMigrationToV2`] wrapped in a
|
||||
/// [`VersionedMigration`](pezframe_support::migrations::VersionedMigration), ensuring the
|
||||
/// migration is only performed when on-chain version is 1.
|
||||
#[allow(dead_code)]
|
||||
pub type MigrationToV2<T> = pezframe_support::migrations::VersionedMigration<
|
||||
1,
|
||||
2,
|
||||
UncheckedMigrationToV2<T>,
|
||||
Pallet<T>,
|
||||
<T as pezframe_system::Config>::DbWeight,
|
||||
>;
|
||||
}
|
||||
|
||||
pub mod v3 {
|
||||
use super::*;
|
||||
use crate::*;
|
||||
|
||||
/// Status of the inbound XCMP channels.
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(crate) type InboundXcmpStatus<T: Config> =
|
||||
StorageValue<Pallet<T>, Vec<InboundChannelDetails>, OptionQuery>;
|
||||
|
||||
/// Inbound aggregate XCMP messages. It can only be one per ParaId/block.
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(crate) type InboundXcmpMessages<T: Config> = StorageDoubleMap<
|
||||
Pallet<T>,
|
||||
Blake2_128Concat,
|
||||
ParaId,
|
||||
Twox64Concat,
|
||||
RelayBlockNumber,
|
||||
Vec<u8>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(crate) type QueueConfig<T: Config> =
|
||||
StorageValue<Pallet<T>, v2::QueueConfigData, ValueQuery>;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
|
||||
pub struct InboundChannelDetails {
|
||||
/// The `ParaId` of the teyrchain that this channel is connected with.
|
||||
pub sender: ParaId,
|
||||
/// The state of the channel.
|
||||
pub state: InboundState,
|
||||
/// The ordered metadata of each inbound message.
|
||||
///
|
||||
/// Contains info about the relay block number that the message was sent at, and the format
|
||||
/// of the incoming message.
|
||||
pub message_metadata: Vec<(RelayBlockNumber, XcmpMessageFormat)>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, TypeInfo,
|
||||
)]
|
||||
pub enum InboundState {
|
||||
Ok,
|
||||
Suspended,
|
||||
}
|
||||
|
||||
/// Migrates the pallet storage to v3.
|
||||
pub struct UncheckedMigrationToV3<T: Config>(PhantomData<T>);
|
||||
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV3<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
#[pezframe_support::storage_alias]
|
||||
type Overweight<T: Config> =
|
||||
CountedStorageMap<Pallet<T>, Twox64Concat, OverweightIndex, ParaId>;
|
||||
let overweight_messages = Overweight::<T>::initialize_counter() as u64;
|
||||
|
||||
T::DbWeight::get().reads_writes(overweight_messages, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// [`UncheckedMigrationToV3`] wrapped in a
|
||||
/// [`VersionedMigration`](pezframe_support::migrations::VersionedMigration), ensuring the
|
||||
/// migration is only performed when on-chain version is 2.
|
||||
pub type MigrationToV3<T> = pezframe_support::migrations::VersionedMigration<
|
||||
2,
|
||||
3,
|
||||
UncheckedMigrationToV3<T>,
|
||||
Pallet<T>,
|
||||
<T as pezframe_system::Config>::DbWeight,
|
||||
>;
|
||||
|
||||
pub fn lazy_migrate_inbound_queue<T: Config>() {
|
||||
let Some(mut states) = v3::InboundXcmpStatus::<T>::get() else {
|
||||
tracing::debug!(target: LOG, "Lazy migration finished: item gone");
|
||||
return;
|
||||
};
|
||||
let Some(ref mut next) = states.first_mut() else {
|
||||
tracing::debug!(target: LOG, "Lazy migration finished: item empty");
|
||||
v3::InboundXcmpStatus::<T>::kill();
|
||||
return;
|
||||
};
|
||||
tracing::debug!(
|
||||
target: LOG,
|
||||
sibling=?next.sender,
|
||||
msgs_left=%next.message_metadata.len(),
|
||||
"Migrating inbound HRMP channel."
|
||||
);
|
||||
// We take the last element since the MQ is a FIFO and we want to keep the order.
|
||||
let Some((block_number, format)) = next.message_metadata.pop() else {
|
||||
states.remove(0);
|
||||
v3::InboundXcmpStatus::<T>::put(states);
|
||||
return;
|
||||
};
|
||||
if format != XcmpMessageFormat::ConcatenatedVersionedXcm {
|
||||
tracing::warn!(
|
||||
target: LOG,
|
||||
?format,
|
||||
"Dropping message (not ConcatenatedVersionedXcm)"
|
||||
);
|
||||
v3::InboundXcmpMessages::<T>::remove(&next.sender, &block_number);
|
||||
v3::InboundXcmpStatus::<T>::put(states);
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(msg) = v3::InboundXcmpMessages::<T>::take(&next.sender, &block_number) else {
|
||||
defensive!("Storage corrupted: HRMP message missing:", (next.sender, block_number));
|
||||
v3::InboundXcmpStatus::<T>::put(states);
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(msg): Result<BoundedVec<_, _>, _> = msg.try_into() else {
|
||||
tracing::error!(target: LOG, "Message dropped: too big");
|
||||
v3::InboundXcmpStatus::<T>::put(states);
|
||||
return;
|
||||
};
|
||||
|
||||
// Finally! We have a proper message.
|
||||
T::XcmpQueue::enqueue_message(msg.as_bounded_slice(), next.sender);
|
||||
tracing::debug!(target: LOG, next_sender=?next.sender, ?block_number, "Migrated HRMP message to MQ");
|
||||
v3::InboundXcmpStatus::<T>::put(states);
|
||||
}
|
||||
}
|
||||
|
||||
pub mod v4 {
|
||||
use super::*;
|
||||
|
||||
/// Migrates `QueueConfigData` to v4, removing deprecated fields and bumping page
|
||||
/// thresholds to at least the default values.
|
||||
pub struct UncheckedMigrationToV4<T: Config>(PhantomData<T>);
|
||||
|
||||
impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationToV4<T> {
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
let translate = |pre: v2::QueueConfigData| -> QueueConfigData {
|
||||
let pre_default = v2::QueueConfigData::default();
|
||||
// If the previous values are the default ones, let's replace them with the new
|
||||
// default.
|
||||
if pre.suspend_threshold == pre_default.suspend_threshold &&
|
||||
pre.drop_threshold == pre_default.drop_threshold &&
|
||||
pre.resume_threshold == pre_default.resume_threshold
|
||||
{
|
||||
return QueueConfigData::default();
|
||||
}
|
||||
|
||||
// If the previous values are not the default ones, let's leave them as they are.
|
||||
QueueConfigData {
|
||||
suspend_threshold: pre.suspend_threshold,
|
||||
drop_threshold: pre.drop_threshold,
|
||||
resume_threshold: pre.resume_threshold,
|
||||
}
|
||||
};
|
||||
|
||||
if QueueConfig::<T>::translate(|pre| pre.map(translate)).is_err() {
|
||||
tracing::error!(
|
||||
target: crate::LOG_TARGET,
|
||||
"unexpected error when performing translation of the QueueConfig type \
|
||||
during storage upgrade to v4"
|
||||
);
|
||||
}
|
||||
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// [`UncheckedMigrationToV4`] wrapped in a
|
||||
/// [`VersionedMigration`](pezframe_support::migrations::VersionedMigration), ensuring the
|
||||
/// migration is only performed when on-chain version is 3.
|
||||
pub type MigrationToV4<T> = pezframe_support::migrations::VersionedMigration<
|
||||
3,
|
||||
4,
|
||||
UncheckedMigrationToV4<T>,
|
||||
Pallet<T>,
|
||||
<T as pezframe_system::Config>::DbWeight,
|
||||
>;
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "try-runtime", test))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Test};
|
||||
use pezframe_support::traits::OnRuntimeUpgrade;
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn test_migration_to_v2() {
|
||||
let v1 = v1::QueueConfigData {
|
||||
suspend_threshold: 5,
|
||||
drop_threshold: 12,
|
||||
resume_threshold: 3,
|
||||
threshold_weight: 333_333,
|
||||
weight_restrict_decay: 1,
|
||||
xcmp_max_individual_weight: 10_000_000_000,
|
||||
};
|
||||
|
||||
new_test_ext().execute_with(|| {
|
||||
let storage_version = StorageVersion::new(1);
|
||||
storage_version.put::<Pallet<Test>>();
|
||||
|
||||
pezframe_support::storage::unhashed::put_raw(
|
||||
&crate::QueueConfig::<Test>::hashed_key(),
|
||||
&v1.encode(),
|
||||
);
|
||||
|
||||
let bytes = v2::MigrationToV2::<Test>::pre_upgrade();
|
||||
assert!(bytes.is_ok());
|
||||
v2::MigrationToV2::<Test>::on_runtime_upgrade();
|
||||
assert!(v2::MigrationToV2::<Test>::post_upgrade(bytes.unwrap()).is_ok());
|
||||
|
||||
let v2 = v2::QueueConfig::<Test>::get();
|
||||
|
||||
assert_eq!(v1.suspend_threshold, v2.suspend_threshold);
|
||||
assert_eq!(v1.drop_threshold, v2.drop_threshold);
|
||||
assert_eq!(v1.resume_threshold, v2.resume_threshold);
|
||||
assert_eq!(v1.threshold_weight, v2.threshold_weight.ref_time());
|
||||
assert_eq!(v1.weight_restrict_decay, v2.weight_restrict_decay.ref_time());
|
||||
assert_eq!(v1.xcmp_max_individual_weight, v2.xcmp_max_individual_weight.ref_time());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn test_migration_to_v4() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let storage_version = StorageVersion::new(3);
|
||||
storage_version.put::<Pallet<Test>>();
|
||||
|
||||
let v2 = v2::QueueConfigData {
|
||||
drop_threshold: 5,
|
||||
suspend_threshold: 2,
|
||||
resume_threshold: 1,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pezframe_support::storage::unhashed::put_raw(
|
||||
&crate::QueueConfig::<Test>::hashed_key(),
|
||||
&v2.encode(),
|
||||
);
|
||||
|
||||
let bytes = v4::MigrationToV4::<Test>::pre_upgrade();
|
||||
assert!(bytes.is_ok());
|
||||
v4::MigrationToV4::<Test>::on_runtime_upgrade();
|
||||
assert!(v4::MigrationToV4::<Test>::post_upgrade(bytes.unwrap()).is_ok());
|
||||
|
||||
let v4 = QueueConfig::<Test>::get();
|
||||
|
||||
assert_eq!(
|
||||
v4,
|
||||
QueueConfigData { suspend_threshold: 32, drop_threshold: 48, resume_threshold: 8 }
|
||||
);
|
||||
});
|
||||
|
||||
new_test_ext().execute_with(|| {
|
||||
let storage_version = StorageVersion::new(3);
|
||||
storage_version.put::<Pallet<Test>>();
|
||||
|
||||
let v2 = v2::QueueConfigData {
|
||||
drop_threshold: 100,
|
||||
suspend_threshold: 50,
|
||||
resume_threshold: 40,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pezframe_support::storage::unhashed::put_raw(
|
||||
&crate::QueueConfig::<Test>::hashed_key(),
|
||||
&v2.encode(),
|
||||
);
|
||||
|
||||
let bytes = v4::MigrationToV4::<Test>::pre_upgrade();
|
||||
assert!(bytes.is_ok());
|
||||
v4::MigrationToV4::<Test>::on_runtime_upgrade();
|
||||
assert!(v4::MigrationToV4::<Test>::post_upgrade(bytes.unwrap()).is_ok());
|
||||
|
||||
let v4 = QueueConfig::<Test>::get();
|
||||
|
||||
assert_eq!(
|
||||
v4,
|
||||
QueueConfigData {
|
||||
suspend_threshold: 50,
|
||||
drop_threshold: 100,
|
||||
resume_threshold: 40
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// 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 to version 5.
|
||||
|
||||
use crate::*;
|
||||
use alloc::vec::Vec;
|
||||
use pezcumulus_primitives_core::ListChannelInfos;
|
||||
use pezframe_support::{pezpallet_prelude::*, traits::UncheckedOnRuntimeUpgrade};
|
||||
|
||||
/// Configs needed to run the V5 migration.
|
||||
pub trait V5Config: Config {
|
||||
/// List all outbound channels with their target `ParaId` and maximum message size.
|
||||
type ChannelList: ListChannelInfos;
|
||||
}
|
||||
|
||||
/// Ensures that the storage migrates cleanly to V5.
|
||||
///
|
||||
/// The migration itself is a no-op, but it checks that none of the `BoundedVec`s would truncate on
|
||||
/// the next decode after the upgrade was applied.
|
||||
pub type MigrateV4ToV5<T> = pezframe_support::migrations::VersionedMigration<
|
||||
4,
|
||||
5,
|
||||
unversioned::UncheckedMigrateV4ToV5<T>,
|
||||
Pallet<T>,
|
||||
<T as pezframe_system::Config>::DbWeight,
|
||||
>;
|
||||
|
||||
// V4 storage aliases
|
||||
mod v4 {
|
||||
use super::*;
|
||||
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(super) type OutboundXcmpStatus<T: Config> =
|
||||
StorageValue<Pallet<T>, Vec<OutboundChannelDetails>, ValueQuery>;
|
||||
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(super) type OutboundXcmpMessages<T: Config> = StorageDoubleMap<
|
||||
Pallet<T>,
|
||||
Blake2_128Concat,
|
||||
ParaId,
|
||||
Twox64Concat,
|
||||
u16,
|
||||
Vec<u8>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
#[pezframe_support::storage_alias]
|
||||
pub(super) type SignalMessages<T: Config> =
|
||||
StorageMap<Pallet<T>, Blake2_128Concat, ParaId, Vec<u8>, ValueQuery>;
|
||||
}
|
||||
|
||||
// Private module to hide the migration.
|
||||
mod unversioned {
|
||||
/// Please use [`MigrateV4ToV5`] instead.
|
||||
pub struct UncheckedMigrateV4ToV5<T: super::V5Config>(core::marker::PhantomData<T>);
|
||||
}
|
||||
|
||||
impl<T: V5Config> UncheckedOnRuntimeUpgrade for unversioned::UncheckedMigrateV4ToV5<T> {
|
||||
fn on_runtime_upgrade() -> pezframe_support::weights::Weight {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn post_upgrade(_: Vec<u8>) -> Result<(), pezsp_runtime::DispatchError> {
|
||||
// We dont need any front-run protection for this since channels are opened by governance.
|
||||
ensure!(
|
||||
v4::OutboundXcmpStatus::<T>::get().len() as u32 <= T::MaxActiveOutboundChannels::get(),
|
||||
"Too many outbound channels. Close some channels or increase `MaxActiveOutboundChannels`."
|
||||
);
|
||||
|
||||
ensure!(T::MaxPageSize::get() >= 16, "Sanity check failed: MaxPageSize too small");
|
||||
|
||||
// Check if any channels have a too large message max sizes.
|
||||
let max_msg_len = T::MaxPageSize::get() - XcmpMessageFormat::max_encoded_len() as u32;
|
||||
for channel in T::ChannelList::outgoing_channels() {
|
||||
let info = T::ChannelInfo::get_channel_info(channel)
|
||||
.expect("All listed channels must provide info");
|
||||
|
||||
if info.max_message_size > max_msg_len {
|
||||
tracing::error!(
|
||||
target: "runtime::xcmp-queue-migration::v5",
|
||||
channel_max=%info.max_message_size,
|
||||
max_page_size=%max_msg_len,
|
||||
"Max message size for channel is too large. This means that the V5 \
|
||||
migration can be front-run and an attacker could place a large message just right \
|
||||
before the migration to make other messages un-decodable. Please either increase \
|
||||
`MaxPageSize` or decrease the `max_message_size` for this channel."
|
||||
);
|
||||
return Err("Migration can be front-run".into());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
// 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.
|
||||
|
||||
use super::*;
|
||||
use crate as xcmp_queue;
|
||||
use alloc::collections::BTreeMap;
|
||||
use core::marker::PhantomData;
|
||||
use pezcumulus_pezpallet_teyrchain_system::AnyRelayNumber;
|
||||
use pezcumulus_primitives_core::{ChannelInfo, IsSystem, ParaId};
|
||||
use pezframe_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{BatchesFootprints, ConstU32, Everything, OriginTrait},
|
||||
BoundedSlice,
|
||||
};
|
||||
use pezframe_system::EnsureRoot;
|
||||
use pezsp_core::H256;
|
||||
use pezsp_runtime::{
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
BuildStorage,
|
||||
};
|
||||
use xcm::prelude::*;
|
||||
use xcm_executor::traits::ConvertOrigin;
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
// Configure a mock runtime to test the pallet.
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
Balances: pezpallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
TeyrchainSystem: pezcumulus_pezpallet_teyrchain_system::{
|
||||
Pallet, Call, Config<T>, Storage, Inherent, Event<T>,
|
||||
},
|
||||
XcmpQueue: xcmp_queue::{Pallet, Call, Storage, Event<T>},
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const SS58Prefix: u8 = 42;
|
||||
}
|
||||
|
||||
type AccountId = u64;
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type BaseCallFilter = Everything;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Nonce = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Block = Block;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = pezcumulus_pezpallet_teyrchain_system::TeyrchainSetCode<Test>;
|
||||
type MaxConsumers = pezframe_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 5;
|
||||
}
|
||||
|
||||
pub type Balance = u64;
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
impl pezcumulus_pezpallet_teyrchain_system::Config for Test {
|
||||
type WeightInfo = ();
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type OnSystemEvent = ();
|
||||
type SelfParaId = ();
|
||||
type OutboundXcmpMessageSource = XcmpQueue;
|
||||
// Ignore all DMP messages by enqueueing them into `()`:
|
||||
type DmpQueue = pezframe_support::traits::EnqueueWithOrigin<(), pezsp_core::ConstU8<0>>;
|
||||
type ReservedDmpWeight = ();
|
||||
type XcmpMessageHandler = XcmpQueue;
|
||||
type ReservedXcmpWeight = ();
|
||||
type CheckAssociatedRelayNumber = AnyRelayNumber;
|
||||
type ConsensusHook = pezcumulus_pezpallet_teyrchain_system::consensus_hook::ExpectParentIncluded;
|
||||
type RelayParentOffset = ConstU32<0>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const RelayChain: Location = Location::parent();
|
||||
pub UniversalLocation: InteriorLocation = [Teyrchain(1u32)].into();
|
||||
pub UnitWeightCost: Weight = Weight::from_parts(1_000_000, 1024);
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
pub const MaxAssetsIntoHolding: u32 = 64;
|
||||
}
|
||||
|
||||
pub struct SystemTeyrchainAsSuperuser<RuntimeOrigin>(PhantomData<RuntimeOrigin>);
|
||||
impl<RuntimeOrigin: OriginTrait> ConvertOrigin<RuntimeOrigin>
|
||||
for SystemTeyrchainAsSuperuser<RuntimeOrigin>
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
if kind == OriginKind::Superuser &&
|
||||
matches!(
|
||||
origin.unpack(),
|
||||
(1, [Teyrchain(id)]) if ParaId::from(*id).is_system(),
|
||||
) {
|
||||
Ok(RuntimeOrigin::root())
|
||||
} else {
|
||||
Err(origin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static EnqueuedMessages: Vec<(ParaId, Vec<u8>)> = Default::default();
|
||||
pub static FirstPagePos: BTreeMap<ParaId, usize> = Default::default();
|
||||
}
|
||||
|
||||
/// An `EnqueueMessage` implementation that puts all messages in thread-local storage.
|
||||
pub struct EnqueueToLocalStorage<T>(PhantomData<T>);
|
||||
|
||||
impl<T: OnQueueChanged<ParaId>> EnqueueMessage<ParaId> for EnqueueToLocalStorage<T> {
|
||||
type MaxMessageLen = pezsp_core::ConstU32<256>;
|
||||
|
||||
fn enqueue_message(message: BoundedSlice<u8, Self::MaxMessageLen>, origin: ParaId) {
|
||||
let mut msgs = EnqueuedMessages::get();
|
||||
msgs.push((origin, message.to_vec()));
|
||||
EnqueuedMessages::set(msgs);
|
||||
T::on_queue_changed(origin, Self::footprint(origin));
|
||||
}
|
||||
|
||||
fn enqueue_messages<'a>(
|
||||
iter: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
|
||||
origin: ParaId,
|
||||
) {
|
||||
let mut msgs = EnqueuedMessages::get();
|
||||
msgs.extend(iter.map(|m| (origin, m.to_vec())));
|
||||
EnqueuedMessages::set(msgs);
|
||||
T::on_queue_changed(origin, Self::footprint(origin));
|
||||
}
|
||||
|
||||
fn sweep_queue(origin: ParaId) {
|
||||
let mut msgs = EnqueuedMessages::get();
|
||||
msgs.retain(|(o, _)| o != &origin);
|
||||
EnqueuedMessages::set(msgs);
|
||||
T::on_queue_changed(origin, Self::footprint(origin));
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OnQueueChanged<ParaId>> QueueFootprintQuery<ParaId> for EnqueueToLocalStorage<T> {
|
||||
type MaxMessageLen = pezsp_core::ConstU32<256>;
|
||||
|
||||
fn footprint(origin: ParaId) -> QueueFootprint {
|
||||
let msgs = EnqueuedMessages::get();
|
||||
let mut footprint = QueueFootprint::default();
|
||||
for (o, m) in msgs {
|
||||
if o == origin {
|
||||
footprint.storage.count += 1;
|
||||
footprint.storage.size += m.len() as u64;
|
||||
}
|
||||
}
|
||||
// Let's consider that we add one message per page
|
||||
footprint.pages = footprint.storage.count as u32;
|
||||
footprint.ready_pages = footprint.pages;
|
||||
footprint
|
||||
}
|
||||
|
||||
fn get_batches_footprints<'a>(
|
||||
origin: ParaId,
|
||||
msgs: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
|
||||
total_pages_limit: u32,
|
||||
) -> BatchesFootprints {
|
||||
// Let's consider that we add one message per page
|
||||
let footprint = Self::footprint(origin);
|
||||
let mut batches_footprints = BatchesFootprints {
|
||||
first_page_pos: *FirstPagePos::get().entry(origin).or_default(),
|
||||
footprints: vec![],
|
||||
};
|
||||
for (idx, msg) in msgs.enumerate() {
|
||||
if footprint.pages + idx as u32 + 1 > total_pages_limit {
|
||||
break;
|
||||
}
|
||||
|
||||
batches_footprints.push(msg.into(), true);
|
||||
}
|
||||
batches_footprints
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
/// The asset ID for the asset that we use to pay for message delivery fees.
|
||||
pub FeeAssetId: AssetId = AssetId(RelayChain::get());
|
||||
/// The base fee for the message delivery fees.
|
||||
pub const BaseDeliveryFee: Balance = 300_000_000;
|
||||
/// The fee per byte
|
||||
pub const ByteFee: Balance = 1_000_000;
|
||||
}
|
||||
|
||||
pub type PriceForSiblingTeyrchainDelivery = pezkuwi_runtime_common::xcm_sender::ExponentialPrice<
|
||||
FeeAssetId,
|
||||
BaseDeliveryFee,
|
||||
ByteFee,
|
||||
XcmpQueue,
|
||||
>;
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type ChannelInfo = MockedChannelInfo;
|
||||
type VersionWrapper = ();
|
||||
type XcmpQueue = EnqueueToLocalStorage<Pallet<Test>>;
|
||||
type MaxInboundSuspended = ConstU32<1_000>;
|
||||
type MaxActiveOutboundChannels = ConstU32<128>;
|
||||
// Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we
|
||||
// need to set the page size larger than that until we reduce the channel size on-chain.
|
||||
type MaxPageSize = ConstU32<{ 103 * 1024 }>;
|
||||
type ControllerOrigin = EnsureRoot<AccountId>;
|
||||
type ControllerOriginConverter = SystemTeyrchainAsSuperuser<RuntimeOrigin>;
|
||||
type WeightInfo = ();
|
||||
type PriceForSiblingDelivery = PriceForSiblingTeyrchainDelivery;
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap().into()
|
||||
}
|
||||
|
||||
/// A para that we have an HRMP channel with.
|
||||
pub const HRMP_PARA_ID: u32 = 7777;
|
||||
|
||||
pub struct MockedChannelInfo;
|
||||
impl GetChannelInfo for MockedChannelInfo {
|
||||
fn get_channel_status(id: ParaId) -> ChannelStatus {
|
||||
if id == HRMP_PARA_ID.into() {
|
||||
return ChannelStatus::Ready(usize::MAX, usize::MAX);
|
||||
}
|
||||
|
||||
TeyrchainSystem::get_channel_status(id)
|
||||
}
|
||||
|
||||
fn get_channel_info(id: ParaId) -> Option<ChannelInfo> {
|
||||
if id == HRMP_PARA_ID.into() {
|
||||
return Some(ChannelInfo {
|
||||
max_capacity: u32::MAX,
|
||||
max_total_size: u32::MAX,
|
||||
max_message_size: u32::MAX,
|
||||
msg_count: 0,
|
||||
total_size: 0,
|
||||
});
|
||||
}
|
||||
|
||||
TeyrchainSystem::get_channel_info(id)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mk_page() -> Vec<u8> {
|
||||
let mut page = Vec::<u8>::new();
|
||||
|
||||
let newer_xcm_version = xcm::prelude::XCM_VERSION;
|
||||
let older_xcm_version = newer_xcm_version - 1;
|
||||
|
||||
for i in 0..100 {
|
||||
page.extend(match i % 2 {
|
||||
0 => versioned_xcm(older_xcm_version).encode(),
|
||||
1 => versioned_xcm(newer_xcm_version).encode(),
|
||||
// We cannot push an undecodable XCM here since it would break the decode stream.
|
||||
_ => unreachable!(),
|
||||
});
|
||||
}
|
||||
|
||||
page
|
||||
}
|
||||
|
||||
pub(crate) fn versioned_xcm(version: XcmVersion) -> VersionedXcm<()> {
|
||||
let instr = Instruction::<()>::Trap(1);
|
||||
VersionedXcm::from(Xcm::<()>(vec![instr; 3]))
|
||||
.into_version(version)
|
||||
.expect("Version conversion should work")
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,458 @@
|
||||
// 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_xcmp_queue`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 32.0.0
|
||||
//! DATE: 2025-09-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! WORST CASE MAP SIZE: `1000000`
|
||||
//! HOSTNAME: `Serbans-MacBook-Pro.local`, CPU: `<UNKNOWN>`
|
||||
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024`
|
||||
|
||||
// Executed Command:
|
||||
// ./target/release/pezkuwi-teyrchain
|
||||
// benchmark
|
||||
// pallet
|
||||
// --pallet
|
||||
// pezcumulus-pezpallet-xcmp-queue
|
||||
// --chain
|
||||
// asset-hub-zagros-dev
|
||||
// --output
|
||||
// pezcumulus/pezpallets/xcmp-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)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use pezframe_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for `pezcumulus_pezpallet_xcmp_queue`.
|
||||
pub trait WeightInfo {
|
||||
fn set_config_with_u32() -> Weight;
|
||||
fn enqueue_n_bytes_xcmp_message(n: u32, ) -> Weight;
|
||||
fn enqueue_n_empty_xcmp_messages(n: u32, ) -> Weight;
|
||||
fn enqueue_empty_xcmp_message_at(n: u32, ) -> Weight;
|
||||
fn enqueue_n_full_pages(n: u32, ) -> Weight;
|
||||
fn enqueue_1000_small_xcmp_messages() -> Weight;
|
||||
fn suspend_channel() -> Weight;
|
||||
fn resume_channel() -> Weight;
|
||||
fn take_first_concatenated_xcm(n: u32, ) -> Weight;
|
||||
fn on_idle_good_msg() -> Weight;
|
||||
fn on_idle_large_msg() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for `pezcumulus_pezpallet_xcmp_queue` using the Bizinikiwi node and recommended hardware.
|
||||
pub struct BizinikiwiWeight<T>(PhantomData<T>);
|
||||
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:1)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
fn set_config_with_u32() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `175`
|
||||
// Estimated: `1497`
|
||||
// Minimum execution time: 3_000_000 picoseconds.
|
||||
Weight::from_parts(4_000_000, 1497)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// 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: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 105467]`.
|
||||
fn enqueue_n_bytes_xcmp_message(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `251`
|
||||
// Estimated: `5487`
|
||||
// Minimum execution time: 11_000_000 picoseconds.
|
||||
Weight::from_parts(12_262_916, 5487)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(187, 0).saturating_mul(n.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// 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: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 1000]`.
|
||||
fn enqueue_n_empty_xcmp_messages(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `251`
|
||||
// Estimated: `5487`
|
||||
// Minimum execution time: 9_000_000 picoseconds.
|
||||
Weight::from_parts(13_664_993, 5487)
|
||||
// Standard Error: 220
|
||||
.saturating_add(Weight::from_parts(131_195, 0).saturating_mul(n.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::Pages` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `Measured`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `Measured`)
|
||||
/// The range of component `n` is `[0, 105457]`.
|
||||
fn enqueue_empty_xcmp_message_at(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `434 + n * (1 ±0)`
|
||||
// Estimated: `3897 + n * (1 ±0)`
|
||||
// Minimum execution time: 16_000_000 picoseconds.
|
||||
Weight::from_parts(16_490_667, 3897)
|
||||
// Standard Error: 2
|
||||
.saturating_add(Weight::from_parts(720, 0).saturating_mul(n.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// 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: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:100)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 100]`.
|
||||
fn enqueue_n_full_pages(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `286`
|
||||
// Estimated: `5487`
|
||||
// Minimum execution time: 9_000_000 picoseconds.
|
||||
Weight::from_parts(10_000_000, 5487)
|
||||
// Standard Error: 26_047
|
||||
.saturating_add(Weight::from_parts(23_938_725, 0).saturating_mul(n.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into())))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::Pages` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `Measured`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `Measured`)
|
||||
fn enqueue_1000_small_xcmp_messages() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `53167`
|
||||
// Estimated: `56632`
|
||||
// Minimum execution time: 175_000_000 picoseconds.
|
||||
Weight::from_parts(181_000_000, 56632)
|
||||
.saturating_add(T::DbWeight::get().reads(4_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1)
|
||||
/// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`)
|
||||
fn suspend_channel() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `175`
|
||||
// Estimated: `2767`
|
||||
// Minimum execution time: 2_000_000 picoseconds.
|
||||
Weight::from_parts(2_000_000, 2767)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1)
|
||||
/// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`)
|
||||
fn resume_channel() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `210`
|
||||
// Estimated: `2767`
|
||||
// Minimum execution time: 3_000_000 picoseconds.
|
||||
Weight::from_parts(3_000_000, 2767)
|
||||
.saturating_add(T::DbWeight::get().reads(1_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// The range of component `n` is `[0, 92]`.
|
||||
fn take_first_concatenated_xcm(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 1_000_000 picoseconds.
|
||||
Weight::from_parts(1_878_097, 0)
|
||||
// Standard Error: 558
|
||||
.saturating_add(Weight::from_parts(44_593, 0).saturating_mul(n.into()))
|
||||
}
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (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: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
fn on_idle_good_msg() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `105816`
|
||||
// Estimated: `109281`
|
||||
// Minimum execution time: 63_000_000 picoseconds.
|
||||
Weight::from_parts(67_000_000, 109281)
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
}
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (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: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
fn on_idle_large_msg() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `65885`
|
||||
// Estimated: `69350`
|
||||
// Minimum execution time: 42_000_000 picoseconds.
|
||||
Weight::from_parts(47_000_000, 69350)
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests.
|
||||
impl WeightInfo for () {
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:1)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
fn set_config_with_u32() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `175`
|
||||
// Estimated: `1497`
|
||||
// Minimum execution time: 3_000_000 picoseconds.
|
||||
Weight::from_parts(4_000_000, 1497)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// 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: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 105467]`.
|
||||
fn enqueue_n_bytes_xcmp_message(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `251`
|
||||
// Estimated: `5487`
|
||||
// Minimum execution time: 11_000_000 picoseconds.
|
||||
Weight::from_parts(12_262_916, 5487)
|
||||
// Standard Error: 0
|
||||
.saturating_add(Weight::from_parts(187, 0).saturating_mul(n.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// 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: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 1000]`.
|
||||
fn enqueue_n_empty_xcmp_messages(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `251`
|
||||
// Estimated: `5487`
|
||||
// Minimum execution time: 9_000_000 picoseconds.
|
||||
Weight::from_parts(13_664_993, 5487)
|
||||
// Standard Error: 220
|
||||
.saturating_add(Weight::from_parts(131_195, 0).saturating_mul(n.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::Pages` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `Measured`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `Measured`)
|
||||
/// The range of component `n` is `[0, 105457]`.
|
||||
fn enqueue_empty_xcmp_message_at(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `434 + n * (1 ±0)`
|
||||
// Estimated: `3897 + n * (1 ±0)`
|
||||
// Minimum execution time: 16_000_000 picoseconds.
|
||||
Weight::from_parts(16_490_667, 3897)
|
||||
// Standard Error: 2
|
||||
.saturating_add(Weight::from_parts(720, 0).saturating_mul(n.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
.saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into()))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// 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: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:100)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
/// The range of component `n` is `[0, 100]`.
|
||||
fn enqueue_n_full_pages(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `286`
|
||||
// Estimated: `5487`
|
||||
// Minimum execution time: 9_000_000 picoseconds.
|
||||
Weight::from_parts(10_000_000, 5487)
|
||||
// Standard Error: 26_047
|
||||
.saturating_add(Weight::from_parts(23_938_725, 0).saturating_mul(n.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into())))
|
||||
}
|
||||
/// Storage: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::BookStateFor` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`)
|
||||
/// Storage: `MessageQueue::Pages` (r:1 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `Measured`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `Measured`)
|
||||
fn enqueue_1000_small_xcmp_messages() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `53167`
|
||||
// Estimated: `56632`
|
||||
// Minimum execution time: 175_000_000 picoseconds.
|
||||
Weight::from_parts(181_000_000, 56632)
|
||||
.saturating_add(RocksDbWeight::get().reads(4_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1)
|
||||
/// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`)
|
||||
fn suspend_channel() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `175`
|
||||
// Estimated: `2767`
|
||||
// Minimum execution time: 2_000_000 picoseconds.
|
||||
Weight::from_parts(2_000_000, 2767)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1)
|
||||
/// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`)
|
||||
fn resume_channel() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `210`
|
||||
// Estimated: `2767`
|
||||
// Minimum execution time: 3_000_000 picoseconds.
|
||||
Weight::from_parts(3_000_000, 2767)
|
||||
.saturating_add(RocksDbWeight::get().reads(1_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(1_u64))
|
||||
}
|
||||
/// The range of component `n` is `[0, 92]`.
|
||||
fn take_first_concatenated_xcm(n: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `0`
|
||||
// Estimated: `0`
|
||||
// Minimum execution time: 1_000_000 picoseconds.
|
||||
Weight::from_parts(1_878_097, 0)
|
||||
// Standard Error: 558
|
||||
.saturating_add(Weight::from_parts(44_593, 0).saturating_mul(n.into()))
|
||||
}
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (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: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
fn on_idle_good_msg() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `105816`
|
||||
// Estimated: `109281`
|
||||
// Minimum execution time: 63_000_000 picoseconds.
|
||||
Weight::from_parts(67_000_000, 109281)
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1)
|
||||
/// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (r:1 w:1)
|
||||
/// Proof: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6bedc49980ba3aa32b0a189290fd036649` (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: `XcmpQueue::QueueConfig` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::QueueConfig` (`max_values`: Some(1), `max_size`: Some(12), added: 507, mode: `MaxEncodedLen`)
|
||||
/// Storage: `XcmpQueue::InboundXcmpSuspended` (r:1 w:0)
|
||||
/// Proof: `XcmpQueue::InboundXcmpSuspended` (`max_values`: Some(1), `max_size`: Some(4002), added: 4497, mode: `MaxEncodedLen`)
|
||||
/// Storage: `MessageQueue::Pages` (r:0 w:1)
|
||||
/// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(105521), added: 107996, mode: `MaxEncodedLen`)
|
||||
fn on_idle_large_msg() -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `65885`
|
||||
// Estimated: `69350`
|
||||
// Minimum execution time: 42_000_000 picoseconds.
|
||||
Weight::from_parts(47_000_000, 69350)
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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.
|
||||
|
||||
//! Weight-related utilities.
|
||||
|
||||
use crate::weights::WeightInfo;
|
||||
|
||||
use pezframe_support::{traits::BatchFootprint, weights::Weight};
|
||||
use pezsp_runtime::SaturatedConversion;
|
||||
|
||||
pub(crate) fn get_average_page_pos(max_message_len: u32) -> u32 {
|
||||
max_message_len / 2
|
||||
}
|
||||
|
||||
/// Extended weight info.
|
||||
pub trait WeightInfoExt: WeightInfo {
|
||||
fn uncached_enqueue_xcmp_messages() -> Weight {
|
||||
Self::enqueue_n_full_pages(0)
|
||||
}
|
||||
|
||||
fn enqueue_xcmp_messages(
|
||||
first_page_pos: u32,
|
||||
batch_footprint: &BatchFootprint,
|
||||
is_first_sender_batch: bool,
|
||||
) -> Weight {
|
||||
let message_count = batch_footprint.msgs_count.saturated_into();
|
||||
let size_in_bytes = batch_footprint.size_in_bytes.saturated_into();
|
||||
|
||||
// The cost of adding `n` empty pages on the message queue.
|
||||
let pages_overhead = {
|
||||
let full_message_overhead = Self::enqueue_n_full_pages(1)
|
||||
.saturating_sub(Self::enqueue_n_empty_xcmp_messages(1));
|
||||
let n_full_messages_overhead =
|
||||
full_message_overhead.saturating_mul(batch_footprint.new_pages_count as u64);
|
||||
|
||||
Self::enqueue_n_full_pages(batch_footprint.new_pages_count)
|
||||
.saturating_sub(Self::enqueue_n_full_pages(0))
|
||||
.saturating_sub(n_full_messages_overhead)
|
||||
};
|
||||
|
||||
// The overhead of enqueueing `n` empty messages on the message queue.
|
||||
let messages_overhead = {
|
||||
Self::enqueue_n_empty_xcmp_messages(message_count)
|
||||
.saturating_sub(Self::enqueue_n_empty_xcmp_messages(0))
|
||||
};
|
||||
|
||||
// The overhead of enqueueing `n` bytes on the message queue.
|
||||
let bytes_overhead = {
|
||||
Self::enqueue_n_bytes_xcmp_message(size_in_bytes)
|
||||
.saturating_sub(Self::enqueue_n_bytes_xcmp_message(0))
|
||||
};
|
||||
|
||||
// If the messages are not added to the beginning of the first page, the page will be
|
||||
// decoded and re-encoded once. Let's account for this.
|
||||
let pos_overhead = {
|
||||
let mut pos_overhead = Self::enqueue_empty_xcmp_message_at(first_page_pos)
|
||||
.saturating_sub(Self::enqueue_empty_xcmp_message_at(0));
|
||||
// We need to account for the PoV size of the first page in the message queue only the
|
||||
// first time when we access it.
|
||||
if !is_first_sender_batch {
|
||||
pos_overhead = pos_overhead.set_proof_size(0);
|
||||
}
|
||||
pos_overhead
|
||||
};
|
||||
|
||||
pages_overhead
|
||||
.saturating_add(messages_overhead)
|
||||
.saturating_add(bytes_overhead)
|
||||
.saturating_add(pos_overhead)
|
||||
}
|
||||
|
||||
fn check_accuracy<MaxMessageLen: bounded_collections::Get<u32>>(err_margin: f64) {
|
||||
assert!(err_margin < 1f64);
|
||||
|
||||
let estimated_weight =
|
||||
Self::uncached_enqueue_xcmp_messages().saturating_add(Self::enqueue_xcmp_messages(
|
||||
get_average_page_pos(MaxMessageLen::get()),
|
||||
&BatchFootprint { msgs_count: 1000, size_in_bytes: 3000, new_pages_count: 0 },
|
||||
true,
|
||||
));
|
||||
let actual_weight = Self::enqueue_1000_small_xcmp_messages();
|
||||
|
||||
// Check that the ref_time diff is less than err_margin
|
||||
approx::assert_relative_eq!(
|
||||
estimated_weight.ref_time() as f64,
|
||||
actual_weight.ref_time() as f64,
|
||||
max_relative = err_margin
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: WeightInfo> WeightInfoExt for T {}
|
||||
Reference in New Issue
Block a user