HRMP benchmarks (#3876)

* wip template for hrmp benchmarks

* add all of the benchmarks, first draft

* File was not saved :/

* cargo +nightly fmt

* Use configs

* add configs

* Fix rococo

* Final touches

* revert fmt changes, one last time

* Fix wrappings

* Fix a bunch of tests

* cargo run --quiet --release --features=runtime-benchmarks -- benchmark --chain=kusama-dev --steps=50 --repeat=20 --pallet=runtime_parachains::hrmp --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/kusama/src/weights/runtime_parachains_hrmp.rs

* add to westend

* actually use everything

* cargo run --quiet --release --features=runtime-benchmarks -- benchmark --chain=westend-dev --steps=50 --repeat=20 --pallet=runtime_parachains::hrmp --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/westend/src/weights/runtime_parachains_hrmp.rs

* Update runtime/parachains/src/hrmp.rs

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>

* use real weight in wnd

* reorg

* minor cleanup

* weigh some of the internal stuff as well

* cargo run --quiet --release --features=runtime-benchmarks -- benchmark --chain=kusama-dev --steps=50 --repeat=20 --pallet=runtime_parachains::hrmp --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/kusama/src/weights/runtime_parachains_hrmp.rs

* cargo run --quiet --release --features=runtime-benchmarks -- benchmark --chain=westend-dev --steps=50 --repeat=20 --pallet=runtime_parachains::hrmp --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=./runtime/westend/src/weights/runtime_parachains_hrmp.rs

* add files

* Master.into()

* add validation

* fmt

* fmt

* final fixes

* all runtimes build

* undo formatting

* Update runtime/parachains/src/hrmp.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* non-controversial changes

* do it the parachain-way: use const instead of type configs for simplicity.

* borrow assert_storage_consistency_exhaustive

* move assert_storage_consistency_exhaustive to Pallet, so it can be reused for benchmarks as well.

* fix typo

Co-authored-by: Parity Bot <admin@parity.io>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
Co-authored-by: Sergey Shulepov <s.pepyakin@gmail.com>
Co-authored-by: Zeke Mostov <z.mostov@gmail.com>
This commit is contained in:
Kian Paimani
2022-01-21 14:42:39 +01:00
committed by GitHub
parent efe290490a
commit 3cb2d62665
20 changed files with 1323 additions and 222 deletions
+1
View File
@@ -7031,6 +7031,7 @@ dependencies = [
"sp-staking",
"sp-std",
"sp-tracing",
"static_assertions",
"thousands",
"xcm",
"xcm-executor",
+3
View File
@@ -1230,6 +1230,7 @@ impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo<Self>;
}
impl parachains_paras_inherent::Config for Runtime {
@@ -3297,6 +3298,7 @@ sp_api::impl_runtime_apis! {
list_benchmark!(list, extra, runtime_common::slots, Slots);
list_benchmark!(list, extra, runtime_common::paras_registrar, Registrar);
list_benchmark!(list, extra, runtime_parachains::configuration, Configuration);
list_benchmark!(list, extra, runtime_parachains::hrmp, Hrmp);
list_benchmark!(list, extra, runtime_parachains::disputes, ParasDisputes);
list_benchmark!(list, extra, runtime_parachains::initializer, Initializer);
list_benchmark!(list, extra, runtime_parachains::paras_inherent, ParaInherent);
@@ -3377,6 +3379,7 @@ sp_api::impl_runtime_apis! {
add_benchmark!(params, batches, runtime_common::slots, Slots);
add_benchmark!(params, batches, runtime_common::paras_registrar, Registrar);
add_benchmark!(params, batches, runtime_parachains::configuration, Configuration);
add_benchmark!(params, batches, runtime_parachains::hrmp, Hrmp);
add_benchmark!(params, batches, runtime_parachains::disputes, ParasDisputes);
add_benchmark!(params, batches, runtime_parachains::initializer, Initializer);
add_benchmark!(params, batches, runtime_parachains::paras_inherent, ParaInherent);
@@ -47,6 +47,7 @@ pub mod runtime_common_paras_registrar;
pub mod runtime_common_slots;
pub mod runtime_parachains_configuration;
pub mod runtime_parachains_disputes;
pub mod runtime_parachains_hrmp;
pub mod runtime_parachains_initializer;
pub mod runtime_parachains_paras;
pub mod runtime_parachains_paras_inherent;
@@ -0,0 +1,157 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `runtime_parachains::hrmp`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2021-11-05, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 128
// Executed Command:
// target/release/polkadot
// benchmark
// --chain=kusama-dev
// --steps=50
// --repeat=20
// --pallet=runtime_parachains::hrmp
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/kusama/src/weights/runtime_parachains_hrmp.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::Weight};
use sp_std::marker::PhantomData;
/// Weight functions for `runtime_parachains::hrmp`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInfo<T> {
// Storage: Paras ParaLifecycles (r:2 w:0)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_init_open_channel() -> Weight {
(54_952_000 as Weight)
.saturating_add(T::DbWeight::get().reads(10 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Paras ParaLifecycles (r:1 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_accept_open_channel() -> Weight {
(47_965_000 as Weight)
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_close_channel() -> Weight {
(44_369_000 as Weight)
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:127 w:127)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1)
// Storage: Hrmp HrmpChannelContents (r:0 w:127)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1)
fn force_clean_hrmp(i: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 17_000
.saturating_add((15_959_000 as Weight).saturating_mul(i as Weight))
// Standard Error: 17_000
.saturating_add((16_048_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(e as Weight)))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(e as Weight)))
}
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
// Storage: Paras ParaLifecycles (r:4 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpChannels (r:0 w:2)
fn force_process_hrmp_open(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 26_000
.saturating_add((35_598_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((7 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((6 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpChannels (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:2)
// Storage: Hrmp HrmpChannelContents (r:0 w:2)
fn force_process_hrmp_close(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 15_000
.saturating_add((20_510_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((5 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
fn hrmp_cancel_open_request(c: u32, ) -> Weight {
(32_749_000 as Weight)
// Standard Error: 0
.saturating_add((59_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
fn clean_open_channel_requests(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 6_000
.saturating_add((5_781_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight)))
}
}
+3
View File
@@ -43,6 +43,7 @@ primitives = { package = "polkadot-primitives", path = "../../primitives", defau
rand = { version = "0.8.3", default-features = false }
rand_chacha = { version = "0.3.1", default-features = false }
static_assertions = { version = "1.1.0", optional = true }
polkadot-runtime-metrics = { path = "../metrics", default-features = false}
[dev-dependencies]
@@ -52,6 +53,7 @@ keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substra
frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../primitives/test-helpers"}
sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
thousands = "0.2.0"
assert_matches = "1"
@@ -93,6 +95,7 @@ runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"primitives/runtime-benchmarks",
"static_assertions",
]
try-runtime = [
"frame-support/try-runtime",
@@ -319,6 +319,10 @@ pub enum InconsistentError<BlockNumber> {
},
/// `validation_upgrade_delay` is less than or equal 1.
ValidationUpgradeDelayIsTooLow { validation_upgrade_delay: BlockNumber },
/// Maximum number of HRMP outbound channels exceeded.
MaxHrmpOutboundChannelsExceeded,
/// Maximum number of HRMP inbound channels exceeded.
MaxHrmpInboundChannelsExceeded,
}
impl<BlockNumber> HostConfiguration<BlockNumber>
@@ -381,6 +385,15 @@ where
})
}
if self.hrmp_max_parachain_outbound_channels > crate::hrmp::HRMP_MAX_OUTBOUND_CHANNELS_BOUND
{
return Err(MaxHrmpOutboundChannelsExceeded)
}
if self.hrmp_max_parachain_inbound_channels > crate::hrmp::HRMP_MAX_INBOUND_CHANNELS_BOUND {
return Err(MaxHrmpInboundChannelsExceeded)
}
Ok(())
}
@@ -1608,11 +1621,11 @@ mod tests {
hrmp_recipient_deposit: 4905,
hrmp_channel_max_capacity: 3921,
hrmp_channel_max_total_size: 7687,
hrmp_max_parachain_inbound_channels: 3722,
hrmp_max_parathread_inbound_channels: 1967,
hrmp_max_parachain_inbound_channels: 37,
hrmp_max_parathread_inbound_channels: 19,
hrmp_channel_max_message_size: 8192,
hrmp_max_parachain_outbound_channels: 100,
hrmp_max_parathread_outbound_channels: 200,
hrmp_max_parachain_outbound_channels: 10,
hrmp_max_parathread_outbound_channels: 20,
hrmp_max_message_num_per_candidate: 20,
ump_max_individual_weight: 909,
pvf_checking_enabled: true,
+340 -217
View File
@@ -35,6 +35,58 @@ use sp_std::{
pub use pallet::*;
/// Maximum bound that can be set for inbound channels.
///
/// If inaccurate, the weighing of this pallet might become inaccurate. It is expected form the
/// `configurations` pallet to check these values before setting
pub const HRMP_MAX_INBOUND_CHANNELS_BOUND: u32 = 128;
/// Same as [`HRMP_MAX_INBOUND_CHANNELS_BOUND`], but for outbound channels.
pub const HRMP_MAX_OUTBOUND_CHANNELS_BOUND: u32 = 128;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
pub trait WeightInfo {
fn hrmp_init_open_channel() -> Weight;
fn hrmp_accept_open_channel() -> Weight;
fn hrmp_close_channel() -> Weight;
fn force_clean_hrmp(i: u32, e: u32) -> Weight;
fn force_process_hrmp_open(c: u32) -> Weight;
fn force_process_hrmp_close(c: u32) -> Weight;
fn hrmp_cancel_open_request(c: u32) -> Weight;
fn clean_open_channel_requests(c: u32) -> Weight;
}
/// A weight info that is only suitable for testing.
pub struct TestWeightInfo;
impl WeightInfo for TestWeightInfo {
fn hrmp_accept_open_channel() -> Weight {
Weight::MAX
}
fn force_clean_hrmp(_: u32, _: u32) -> Weight {
Weight::MAX
}
fn force_process_hrmp_close(_: u32) -> Weight {
Weight::MAX
}
fn force_process_hrmp_open(_: u32) -> Weight {
Weight::MAX
}
fn hrmp_cancel_open_request(_: u32) -> Weight {
Weight::MAX
}
fn hrmp_close_channel() -> Weight {
Weight::MAX
}
fn hrmp_init_open_channel() -> Weight {
Weight::MAX
}
fn clean_open_channel_requests(_: u32) -> Weight {
Weight::MAX
}
}
/// A description of a request to open an HRMP channel.
#[derive(Encode, Decode, TypeInfo)]
pub struct HrmpOpenChannelRequest {
@@ -192,10 +244,13 @@ pub mod pallet {
/// An interface for reserving deposits for opening channels.
///
/// NOTE that this Currency instance will be charged with the amounts defined in the `Configuration`
/// pallet. Specifically, that means that the `Balance` of the `Currency` implementation should
/// be the same as `Balance` as used in the `Configuration`.
/// NOTE that this Currency instance will be charged with the amounts defined in the
/// `Configuration` pallet. Specifically, that means that the `Balance` of the `Currency`
/// implementation should be the same as `Balance` as used in the `Configuration`.
type Currency: ReservableCurrency<Self::AccountId>;
/// Something that provides the weight of this pallet.
type WeightInfo: WeightInfo;
}
#[pallet::event]
@@ -251,6 +306,8 @@ pub mod pallet {
OpenHrmpChannelDoesntExist,
/// Cannot cancel an HRMP open channel request because it is already confirmed.
OpenHrmpChannelAlreadyConfirmed,
/// The provided witness data is wrong.
WrongWitness,
}
/// The set of pending HRMP open channel requests.
@@ -263,13 +320,16 @@ pub mod pallet {
pub type HrmpOpenChannelRequests<T: Config> =
StorageMap<_, Twox64Concat, HrmpChannelId, HrmpOpenChannelRequest>;
// NOTE: could become bounded, but we don't have a global maximum for this.
// `HRMP_MAX_INBOUND_CHANNELS_BOUND` are per parachain/parathread, while this storage tracks the
// global state.
#[pallet::storage]
pub type HrmpOpenChannelRequestsList<T: Config> =
StorageValue<_, Vec<HrmpChannelId>, ValueQuery>;
/// This mapping tracks how many open channel requests are initiated by a given sender para.
/// Invariant: `HrmpOpenChannelRequests` should contain the same number of items that has `(X, _)`
/// as the number of `HrmpOpenChannelRequestCount` for `X`.
/// Invariant: `HrmpOpenChannelRequests` should contain the same number of items that has
/// `(X, _)` as the number of `HrmpOpenChannelRequestCount` for `X`.
#[pallet::storage]
pub type HrmpOpenChannelRequestCount<T: Config> =
StorageMap<_, Twox64Concat, ParaId, u32, ValueQuery>;
@@ -281,8 +341,8 @@ pub mod pallet {
pub type HrmpAcceptedChannelRequestCount<T: Config> =
StorageMap<_, Twox64Concat, ParaId, u32, ValueQuery>;
/// A set of pending HRMP close channel requests that are going to be closed during the session change.
/// Used for checking if a given channel is registered for closure.
/// A set of pending HRMP close channel requests that are going to be closed during the session
/// change. Used for checking if a given channel is registered for closure.
///
/// The set is accompanied by a list for iteration.
///
@@ -307,17 +367,17 @@ pub mod pallet {
#[pallet::storage]
pub type HrmpChannels<T: Config> = StorageMap<_, Twox64Concat, HrmpChannelId, HrmpChannel>;
/// Ingress/egress indexes allow to find all the senders and receivers given the opposite
/// side. I.e.
/// Ingress/egress indexes allow to find all the senders and receivers given the opposite side.
/// I.e.
///
/// (a) ingress index allows to find all the senders for a given recipient.
/// (b) egress index allows to find all the recipients for a given sender.
///
/// Invariants:
/// - for each ingress index entry for `P` each item `I` in the index should present in `HrmpChannels`
/// as `(I, P)`.
/// - for each egress index entry for `P` each item `E` in the index should present in `HrmpChannels`
/// as `(P, E)`.
/// - for each ingress index entry for `P` each item `I` in the index should present in
/// `HrmpChannels` as `(I, P)`.
/// - for each egress index entry for `P` each item `E` in the index should present in
/// `HrmpChannels` as `(P, E)`.
/// - there should be no other dangling channels in `HrmpChannels`.
/// - the vectors are sorted.
#[pallet::storage]
@@ -341,27 +401,28 @@ pub mod pallet {
ValueQuery,
>;
/// Maintains a mapping that can be used to answer the question:
/// What paras sent a message at the given block number for a given receiver.
/// Invariants:
/// Maintains a mapping that can be used to answer the question: What paras sent a message at
/// the given block number for a given receiver. Invariants:
/// - The inner `Vec<ParaId>` is never empty.
/// - The inner `Vec<ParaId>` cannot store two same `ParaId`.
/// - The outer vector is sorted ascending by block number and cannot store two items with the same
/// block number.
/// - The outer vector is sorted ascending by block number and cannot store two items with the
/// same block number.
#[pallet::storage]
pub type HrmpChannelDigests<T: Config> =
StorageMap<_, Twox64Concat, ParaId, Vec<(T::BlockNumber, Vec<ParaId>)>, ValueQuery>;
/// Preopen the given HRMP channels.
///
/// The values in the tuple corresponds to `(sender, recipient, max_capacity, max_message_size)`,
/// i.e. similar to `init_open_channel`. In fact, the initialization is performed as if
/// the `init_open_channel` and `accept_open_channel` were called with the respective parameters
/// and the session change take place.
/// The values in the tuple corresponds to
/// `(sender, recipient, max_capacity, max_message_size)`, i.e. similar to `init_open_channel`.
/// In fact, the initialization is performed as if the `init_open_channel` and
/// `accept_open_channel` were called with the respective parameters and the session change take
/// place.
///
/// As such, each channel initializer should satisfy the same constraints, namely:
///
/// 1. `max_capacity` and `max_message_size` should be within the limits set by the configuration pallet.
/// 1. `max_capacity` and `max_message_size` should be within the limits set by the
/// configuration pallet.
/// 2. `sender` and `recipient` must be valid paras.
#[pallet::genesis_config]
pub struct GenesisConfig {
@@ -394,7 +455,7 @@ pub mod pallet {
///
/// The channel can be opened only after the recipient confirms it and only on a session
/// change.
#[pallet::weight(0)]
#[pallet::weight(<T as Config>::WeightInfo::hrmp_init_open_channel())]
pub fn hrmp_init_open_channel(
origin: OriginFor<T>,
recipient: ParaId,
@@ -420,7 +481,7 @@ pub mod pallet {
/// Accept a pending open channel request from the given sender.
///
/// The channel will be opened only on the next session boundary.
#[pallet::weight(0)]
#[pallet::weight(<T as Config>::WeightInfo::hrmp_accept_open_channel())]
pub fn hrmp_accept_open_channel(origin: OriginFor<T>, sender: ParaId) -> DispatchResult {
let origin = ensure_parachain(<T as Config>::Origin::from(origin))?;
Self::accept_open_channel(origin, sender)?;
@@ -432,7 +493,7 @@ pub mod pallet {
/// recipient in the channel being closed.
///
/// The closure can only happen on a session change.
#[pallet::weight(0)]
#[pallet::weight(<T as Config>::WeightInfo::hrmp_close_channel())]
pub fn hrmp_close_channel(
origin: OriginFor<T>,
channel_id: HrmpChannelId,
@@ -448,8 +509,15 @@ pub mod pallet {
/// you to trigger the cleanup immediately for a specific parachain.
///
/// Origin must be Root.
#[pallet::weight(0)]
pub fn force_clean_hrmp(origin: OriginFor<T>, para: ParaId) -> DispatchResult {
///
/// Number of inbound and outbound channels for `para` must be provided as witness data of weighing.
#[pallet::weight(<T as Config>::WeightInfo::force_clean_hrmp(*_inbound, *_outbound))]
pub fn force_clean_hrmp(
origin: OriginFor<T>,
para: ParaId,
_inbound: u32,
_outbound: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::clean_hrmp_after_outgoing(&para);
Ok(())
@@ -459,8 +527,10 @@ pub mod pallet {
///
/// If there are pending HRMP open channel requests, you can use this
/// function process all of those requests immediately.
#[pallet::weight(0)]
pub fn force_process_hrmp_open(origin: OriginFor<T>) -> DispatchResult {
///
/// Total number of opening channels must be provided as witness data of weighing.
#[pallet::weight(<T as Config>::WeightInfo::force_process_hrmp_open(*_channels))]
pub fn force_process_hrmp_open(origin: OriginFor<T>, _channels: u32) -> DispatchResult {
ensure_root(origin)?;
let host_config = configuration::Pallet::<T>::config();
Self::process_hrmp_open_channel_requests(&host_config);
@@ -471,24 +541,35 @@ pub mod pallet {
///
/// If there are pending HRMP close channel requests, you can use this
/// function process all of those requests immediately.
#[pallet::weight(0)]
pub fn force_process_hrmp_close(origin: OriginFor<T>) -> DispatchResult {
///
/// Total number of closing channels must be provided as witness data of weighing.
#[pallet::weight(<T as Config>::WeightInfo::force_process_hrmp_close(*_channels))]
pub fn force_process_hrmp_close(origin: OriginFor<T>, _channels: u32) -> DispatchResult {
ensure_root(origin)?;
Self::process_hrmp_close_channel_requests();
Ok(())
}
/// This cancels a pending open channel request. It can be canceled be either of the sender
/// This cancels a pending open channel request. It can be canceled by either of the sender
/// or the recipient for that request. The origin must be either of those.
///
/// The cancellation happens immediately. It is not possible to cancel the request if it is
/// already accepted.
#[pallet::weight(0)]
///
/// Total number of open requests (i.e. `HrmpOpenChannelRequestsList`) must be provided as
/// witness data.
#[pallet::weight(<T as Config>::WeightInfo::hrmp_cancel_open_request(*open_requests))]
pub fn hrmp_cancel_open_request(
origin: OriginFor<T>,
channel_id: HrmpChannelId,
open_requests: u32,
) -> DispatchResult {
let origin = ensure_parachain(<T as Config>::Origin::from(origin))?;
ensure!(
<Self as Store>::HrmpOpenChannelRequestsList::decode_len().unwrap_or_default()
as u32 <= open_requests,
Error::<T>::WrongWitness
);
Self::cancel_open_request(origin, channel_id.clone())?;
Self::deposit_event(Event::OpenChannelCanceled(origin, channel_id));
Ok(())
@@ -535,10 +616,16 @@ impl<T: Config> Pallet<T> {
pub(crate) fn initializer_on_new_session(
notification: &initializer::SessionChangeNotification<T::BlockNumber>,
outgoing_paras: &[ParaId],
) {
Self::perform_outgoing_para_cleanup(&notification.prev_config, outgoing_paras);
) -> Weight {
let w1 = Self::perform_outgoing_para_cleanup(&notification.prev_config, outgoing_paras);
Self::process_hrmp_open_channel_requests(&notification.prev_config);
Self::process_hrmp_close_channel_requests();
w1.saturating_add(<T as Config>::WeightInfo::force_process_hrmp_open(
outgoing_paras.len() as u32
))
.saturating_add(<T as Config>::WeightInfo::force_process_hrmp_close(
outgoing_paras.len() as u32
))
}
/// Iterate over all paras that were noted for offboarding and remove all the data
@@ -546,20 +633,32 @@ impl<T: Config> Pallet<T> {
fn perform_outgoing_para_cleanup(
config: &HostConfiguration<T::BlockNumber>,
outgoing: &[ParaId],
) {
Self::clean_open_channel_requests(config, outgoing);
) -> Weight {
let mut w = Self::clean_open_channel_requests(config, outgoing);
for outgoing_para in outgoing {
Self::clean_hrmp_after_outgoing(outgoing_para);
// we need a few extra bits of data to weigh this -- all of this is read internally
// anyways, so no overhead.
let ingress_count = <Self as Store>::HrmpIngressChannelsIndex::decode_len(outgoing_para)
.unwrap_or_default() as u32;
let egress_count = <Self as Store>::HrmpEgressChannelsIndex::decode_len(outgoing_para)
.unwrap_or_default() as u32;
w = w.saturating_add(<T as Config>::WeightInfo::force_clean_hrmp(
ingress_count,
egress_count,
));
}
w
}
// Go over the HRMP open channel requests and remove all in which offboarding paras participate.
//
// This will also perform the refunds for the counterparty if it doesn't offboard.
fn clean_open_channel_requests(
pub(crate) fn clean_open_channel_requests(
config: &HostConfiguration<T::BlockNumber>,
outgoing: &[ParaId],
) {
) -> Weight {
// First collect all the channel ids of the open requests in which there is at least one
// party presents in the outgoing list.
//
@@ -605,6 +704,8 @@ impl<T: Config> Pallet<T> {
Self::decrease_accepted_channel_request_count(req_id.recipient);
}
}
<T as Config>::WeightInfo::clean_open_channel_requests(outgoing.len() as u32)
}
/// Remove all storage entries associated with the given para.
@@ -983,8 +1084,8 @@ impl<T: Config> Pallet<T> {
/// Initiate opening a channel from a parachain to a given recipient with given channel
/// parameters.
///
/// Basically the same as [`hrmp_init_open_channel`](Pallet::hrmp_init_open_channel) but intendend for calling directly from
/// other pallets rather than dispatched.
/// Basically the same as [`hrmp_init_open_channel`](Pallet::hrmp_init_open_channel) but
/// intended for calling directly from other pallets rather than dispatched.
pub fn init_open_channel(
origin: ParaId,
recipient: ParaId,
@@ -1037,6 +1138,8 @@ impl<T: Config> Pallet<T> {
config.hrmp_sender_deposit.unique_saturated_into(),
)?;
// mutating storage directly now -- shall not bail henceforth.
<Self as Store>::HrmpOpenChannelRequestCount::insert(&origin, open_req_cnt + 1);
<Self as Store>::HrmpOpenChannelRequests::insert(
&channel_id,
@@ -1067,6 +1170,10 @@ impl<T: Config> Pallet<T> {
{
// this should never happen unless the max downward message size is configured to an
// jokingly small number.
log::error!(
target: "runtime::hrmp",
"sending 'init_open_channel::notification_bytes' failed."
);
debug_assert!(false);
}
@@ -1076,7 +1183,7 @@ impl<T: Config> Pallet<T> {
/// Accept a pending open channel request from the given sender.
///
/// Basically the same as [`hrmp_accept_open_channel`](Pallet::hrmp_accept_open_channel) but
/// intendend for calling directly from other pallets rather than dispatched.
/// intended for calling directly from other pallets rather than dispatched.
pub fn accept_open_channel(origin: ParaId, sender: ParaId) -> DispatchResult {
let channel_id = HrmpChannelId { sender, recipient: origin };
let mut channel_req = <Self as Store>::HrmpOpenChannelRequests::get(&channel_id)
@@ -1121,6 +1228,10 @@ impl<T: Config> Pallet<T> {
{
// this should never happen unless the max downward message size is configured to an
// jokingly small number.
log::error!(
target: "runtime::hrmp",
"sending 'accept_open_channel::notification_bytes' failed."
);
debug_assert!(false);
}
@@ -1195,6 +1306,10 @@ impl<T: Config> Pallet<T> {
{
// this should never happen unless the max downward message size is configured to an
// jokingly small number.
log::error!(
target: "runtime::hrmp",
"sending 'close_channel::notification_bytes' failed."
);
debug_assert!(false);
}
@@ -1262,10 +1377,175 @@ impl<T: Config> Pallet<T> {
});
});
}
#[cfg(any(feature = "runtime-benchmarks", test))]
fn assert_storage_consistency_exhaustive() {
fn assert_is_sorted<T: Ord>(slice: &[T], id: &str) {
assert!(slice.windows(2).all(|xs| xs[0] <= xs[1]), "{} supposed to be sorted", id);
}
let assert_contains_only_onboarded = |paras: Vec<ParaId>, cause: &str| {
for para in paras {
assert!(
crate::paras::Pallet::<T>::is_valid_para(para),
"{}: {:?} para is offboarded",
cause,
para
);
}
};
assert_eq!(
<Self as Store>::HrmpOpenChannelRequests::iter()
.map(|(k, _)| k)
.collect::<BTreeSet<_>>(),
<Self as Store>::HrmpOpenChannelRequestsList::get()
.into_iter()
.collect::<BTreeSet<_>>(),
);
// verify that the set of keys in `HrmpOpenChannelRequestCount` corresponds to the set
// of _senders_ in `HrmpOpenChannelRequests`.
//
// having ensured that, we can go ahead and go over all counts and verify that they match.
assert_eq!(
<Self as Store>::HrmpOpenChannelRequestCount::iter()
.map(|(k, _)| k)
.collect::<BTreeSet<_>>(),
<Self as Store>::HrmpOpenChannelRequests::iter()
.map(|(k, _)| k.sender)
.collect::<BTreeSet<_>>(),
);
for (open_channel_initiator, expected_num) in
<Self as Store>::HrmpOpenChannelRequestCount::iter()
{
let actual_num = <Self as Store>::HrmpOpenChannelRequests::iter()
.filter(|(ch, _)| ch.sender == open_channel_initiator)
.count() as u32;
assert_eq!(expected_num, actual_num);
}
// The same as above, but for accepted channel request count. Note that we are interested
// only in confirmed open requests.
assert_eq!(
<Self as Store>::HrmpAcceptedChannelRequestCount::iter()
.map(|(k, _)| k)
.collect::<BTreeSet<_>>(),
<Self as Store>::HrmpOpenChannelRequests::iter()
.filter(|(_, v)| v.confirmed)
.map(|(k, _)| k.recipient)
.collect::<BTreeSet<_>>(),
);
for (channel_recipient, expected_num) in
<Self as Store>::HrmpAcceptedChannelRequestCount::iter()
{
let actual_num = <Self as Store>::HrmpOpenChannelRequests::iter()
.filter(|(ch, v)| ch.recipient == channel_recipient && v.confirmed)
.count() as u32;
assert_eq!(expected_num, actual_num);
}
assert_eq!(
<Self as Store>::HrmpCloseChannelRequests::iter()
.map(|(k, _)| k)
.collect::<BTreeSet<_>>(),
<Self as Store>::HrmpCloseChannelRequestsList::get()
.into_iter()
.collect::<BTreeSet<_>>(),
);
// A HRMP watermark can be None for an onboarded parachain. However, an offboarded parachain
// cannot have an HRMP watermark: it should've been cleanup.
assert_contains_only_onboarded(
<Self as Store>::HrmpWatermarks::iter().map(|(k, _)| k).collect::<Vec<_>>(),
"HRMP watermarks should contain only onboarded paras",
);
// An entry in `HrmpChannels` indicates that the channel is open. Only open channels can
// have contents.
for (non_empty_channel, contents) in <Self as Store>::HrmpChannelContents::iter() {
assert!(<Self as Store>::HrmpChannels::contains_key(&non_empty_channel));
// pedantic check: there should be no empty vectors in storage, those should be modeled
// by a removed kv pair.
assert!(!contents.is_empty());
}
// Senders and recipients must be onboarded. Otherwise, all channels associated with them
// are removed.
assert_contains_only_onboarded(
<Self as Store>::HrmpChannels::iter()
.flat_map(|(k, _)| vec![k.sender, k.recipient])
.collect::<Vec<_>>(),
"senders and recipients in all channels should be onboarded",
);
// Check the docs for `HrmpIngressChannelsIndex` and `HrmpEgressChannelsIndex` in decl
// storage to get an index what are the channel mappings indexes.
//
// Here, from indexes.
//
// ingress egress
//
// a -> [x, y] x -> [a, b]
// b -> [x, z] y -> [a]
// z -> [b]
//
// we derive a list of channels they represent.
//
// (a, x) (a, x)
// (a, y) (a, y)
// (b, x) (b, x)
// (b, z) (b, z)
//
// and then that we compare that to the channel list in the `HrmpChannels`.
let channel_set_derived_from_ingress = <Self as Store>::HrmpIngressChannelsIndex::iter()
.flat_map(|(p, v)| v.into_iter().map(|i| (i, p)).collect::<Vec<_>>())
.collect::<BTreeSet<_>>();
let channel_set_derived_from_egress = <Self as Store>::HrmpEgressChannelsIndex::iter()
.flat_map(|(p, v)| v.into_iter().map(|e| (p, e)).collect::<Vec<_>>())
.collect::<BTreeSet<_>>();
let channel_set_ground_truth = <Self as Store>::HrmpChannels::iter()
.map(|(k, _)| (k.sender, k.recipient))
.collect::<BTreeSet<_>>();
assert_eq!(channel_set_derived_from_ingress, channel_set_derived_from_egress);
assert_eq!(channel_set_derived_from_egress, channel_set_ground_truth);
<Self as Store>::HrmpIngressChannelsIndex::iter()
.map(|(_, v)| v)
.for_each(|v| assert_is_sorted(&v, "HrmpIngressChannelsIndex"));
<Self as Store>::HrmpEgressChannelsIndex::iter()
.map(|(_, v)| v)
.for_each(|v| assert_is_sorted(&v, "HrmpIngressChannelsIndex"));
assert_contains_only_onboarded(
<Self as Store>::HrmpChannelDigests::iter().map(|(k, _)| k).collect::<Vec<_>>(),
"HRMP channel digests should contain only onboarded paras",
);
for (_digest_for_para, digest) in <Self as Store>::HrmpChannelDigests::iter() {
// Assert that items are in **strictly** ascending order. The strictness also implies
// there are no duplicates.
assert!(digest.windows(2).all(|xs| xs[0].0 < xs[1].0));
for (_, mut senders) in digest {
assert!(!senders.is_empty());
// check for duplicates. For that we sort the vector, then perform deduplication.
// if the vector stayed the same, there are no duplicates.
senders.sort();
let orig_senders = senders.clone();
senders.dedup();
assert_eq!(
orig_senders, senders,
"duplicates removed implies existence of duplicates"
);
}
}
}
}
#[cfg(test)]
mod tests {
pub(crate) mod tests {
use super::*;
use crate::mock::{
new_test_ext, Configuration, Event as MockEvent, Hrmp, MockGenesisConfig, Paras,
@@ -1273,7 +1553,7 @@ mod tests {
};
use frame_support::{assert_noop, assert_ok, traits::Currency as _};
use primitives::v1::BlockNumber;
use std::collections::{BTreeMap, HashSet};
use std::collections::BTreeMap;
fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
let config = Configuration::config();
@@ -1317,7 +1597,7 @@ mod tests {
}
#[derive(Debug)]
struct GenesisConfigBuilder {
pub(super) struct GenesisConfigBuilder {
hrmp_channel_max_capacity: u32,
hrmp_channel_max_message_size: u32,
hrmp_max_parathread_outbound_channels: u32,
@@ -1348,7 +1628,7 @@ mod tests {
}
impl GenesisConfigBuilder {
fn build(self) -> crate::mock::MockGenesisConfig {
pub(super) fn build(self) -> crate::mock::MockGenesisConfig {
let mut genesis = default_genesis_config();
let config = &mut genesis.configuration.config;
config.hrmp_channel_max_capacity = self.hrmp_channel_max_capacity;
@@ -1403,167 +1683,10 @@ mod tests {
<Hrmp as Store>::HrmpChannels::get(&HrmpChannelId { sender, recipient }).is_some()
}
fn assert_storage_consistency_exhaustive() {
assert_eq!(
<Hrmp as Store>::HrmpOpenChannelRequests::iter()
.map(|(k, _)| k)
.collect::<HashSet<_>>(),
<Hrmp as Store>::HrmpOpenChannelRequestsList::get()
.into_iter()
.collect::<HashSet<_>>(),
);
// verify that the set of keys in `HrmpOpenChannelRequestCount` corresponds to the set
// of _senders_ in `HrmpOpenChannelRequests`.
//
// having ensured that, we can go ahead and go over all counts and verify that they match.
assert_eq!(
<Hrmp as Store>::HrmpOpenChannelRequestCount::iter()
.map(|(k, _)| k)
.collect::<HashSet<_>>(),
<Hrmp as Store>::HrmpOpenChannelRequests::iter()
.map(|(k, _)| k.sender)
.collect::<HashSet<_>>(),
);
for (open_channel_initiator, expected_num) in
<Hrmp as Store>::HrmpOpenChannelRequestCount::iter()
{
let actual_num = <Hrmp as Store>::HrmpOpenChannelRequests::iter()
.filter(|(ch, _)| ch.sender == open_channel_initiator)
.count() as u32;
assert_eq!(expected_num, actual_num);
}
// The same as above, but for accepted channel request count. Note that we are interested
// only in confirmed open requests.
assert_eq!(
<Hrmp as Store>::HrmpAcceptedChannelRequestCount::iter()
.map(|(k, _)| k)
.collect::<HashSet<_>>(),
<Hrmp as Store>::HrmpOpenChannelRequests::iter()
.filter(|(_, v)| v.confirmed)
.map(|(k, _)| k.recipient)
.collect::<HashSet<_>>(),
);
for (channel_recipient, expected_num) in
<Hrmp as Store>::HrmpAcceptedChannelRequestCount::iter()
{
let actual_num = <Hrmp as Store>::HrmpOpenChannelRequests::iter()
.filter(|(ch, v)| ch.recipient == channel_recipient && v.confirmed)
.count() as u32;
assert_eq!(expected_num, actual_num);
}
assert_eq!(
<Hrmp as Store>::HrmpCloseChannelRequests::iter()
.map(|(k, _)| k)
.collect::<HashSet<_>>(),
<Hrmp as Store>::HrmpCloseChannelRequestsList::get()
.into_iter()
.collect::<HashSet<_>>(),
);
// A HRMP watermark can be None for an onboarded parachain. However, an offboarded parachain
// cannot have an HRMP watermark: it should've been cleanup.
assert_contains_only_onboarded(
<Hrmp as Store>::HrmpWatermarks::iter().map(|(k, _)| k),
"HRMP watermarks should contain only onboarded paras",
);
// An entry in `HrmpChannels` indicates that the channel is open. Only open channels can
// have contents.
for (non_empty_channel, contents) in <Hrmp as Store>::HrmpChannelContents::iter() {
assert!(<Hrmp as Store>::HrmpChannels::contains_key(&non_empty_channel));
// pedantic check: there should be no empty vectors in storage, those should be modeled
// by a removed kv pair.
assert!(!contents.is_empty());
}
// Senders and recipients must be onboarded. Otherwise, all channels associated with them
// are removed.
assert_contains_only_onboarded(
<Hrmp as Store>::HrmpChannels::iter().flat_map(|(k, _)| vec![k.sender, k.recipient]),
"senders and recipients in all channels should be onboarded",
);
// Check the docs for `HrmpIngressChannelsIndex` and `HrmpEgressChannelsIndex` in decl
// storage to get an index what are the channel mappings indexes.
//
// Here, from indexes.
//
// ingress egress
//
// a -> [x, y] x -> [a, b]
// b -> [x, z] y -> [a]
// z -> [b]
//
// we derive a list of channels they represent.
//
// (a, x) (a, x)
// (a, y) (a, y)
// (b, x) (b, x)
// (b, z) (b, z)
//
// and then that we compare that to the channel list in the `HrmpChannels`.
let channel_set_derived_from_ingress = <Hrmp as Store>::HrmpIngressChannelsIndex::iter()
.flat_map(|(p, v)| v.into_iter().map(|i| (i, p)).collect::<Vec<_>>())
.collect::<HashSet<_>>();
let channel_set_derived_from_egress = <Hrmp as Store>::HrmpEgressChannelsIndex::iter()
.flat_map(|(p, v)| v.into_iter().map(|e| (p, e)).collect::<Vec<_>>())
.collect::<HashSet<_>>();
let channel_set_ground_truth = <Hrmp as Store>::HrmpChannels::iter()
.map(|(k, _)| (k.sender, k.recipient))
.collect::<HashSet<_>>();
assert_eq!(channel_set_derived_from_ingress, channel_set_derived_from_egress);
assert_eq!(channel_set_derived_from_egress, channel_set_ground_truth);
<Hrmp as Store>::HrmpIngressChannelsIndex::iter()
.map(|(_, v)| v)
.for_each(|v| assert_is_sorted(&v, "HrmpIngressChannelsIndex"));
<Hrmp as Store>::HrmpEgressChannelsIndex::iter()
.map(|(_, v)| v)
.for_each(|v| assert_is_sorted(&v, "HrmpIngressChannelsIndex"));
assert_contains_only_onboarded(
<Hrmp as Store>::HrmpChannelDigests::iter().map(|(k, _)| k),
"HRMP channel digests should contain only onboarded paras",
);
for (_digest_for_para, digest) in <Hrmp as Store>::HrmpChannelDigests::iter() {
// Assert that items are in **strictly** ascending order. The strictness also implies
// there are no duplicates.
assert!(digest.windows(2).all(|xs| xs[0].0 < xs[1].0));
for (_, mut senders) in digest {
assert!(!senders.is_empty());
// check for duplicates. For that we sort the vector, then perform deduplication.
// if the vector stayed the same, there are no duplicates.
senders.sort();
let orig_senders = senders.clone();
senders.dedup();
assert_eq!(
orig_senders, senders,
"duplicates removed implies existence of duplicates"
);
}
}
fn assert_contains_only_onboarded(iter: impl Iterator<Item = ParaId>, cause: &str) {
for para in iter {
assert!(Paras::is_valid_para(para), "{}: {} para is offboarded", cause, para);
}
}
}
fn assert_is_sorted<T: Ord>(slice: &[T], id: &str) {
assert!(slice.windows(2).all(|xs| xs[0] <= xs[1]), "{} supposed to be sorted", id);
}
#[test]
fn empty_state_consistent_state() {
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
});
}
@@ -1581,12 +1704,12 @@ mod tests {
run_to_block(5, Some(vec![4, 5]));
Hrmp::hrmp_init_open_channel(para_a_origin.into(), para_b, 2, 8).unwrap();
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::OpenChannelRequested(para_a, para_b, 2, 8))));
Hrmp::hrmp_accept_open_channel(para_b_origin.into(), para_a).unwrap();
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::OpenChannelAccepted(para_a, para_b))));
@@ -1594,7 +1717,7 @@ mod tests {
// not been created yet.
run_to_block(6, None);
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
// Now let the session change happen and thus open the channel.
run_to_block(8, Some(vec![8]));
@@ -1624,12 +1747,12 @@ mod tests {
let channel_id = HrmpChannelId { sender: para_a, recipient: para_b };
Hrmp::hrmp_close_channel(para_b_origin.into(), channel_id.clone()).unwrap();
assert!(channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
// After the session change the channel should be closed.
run_to_block(8, Some(vec![8]));
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::ChannelClosed(para_b, channel_id.clone()))));
});
@@ -1662,14 +1785,14 @@ mod tests {
let config = Configuration::config();
assert!(Hrmp::check_outbound_hrmp(&config, para_a, &msgs).is_ok());
let _ = Hrmp::queue_outbound_hrmp(para_a, msgs);
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
// On Block 7:
// B receives the message sent by A. B sets the watermark to 6.
run_to_block(7, None);
assert!(Hrmp::check_hrmp_watermark(para_b, 7, 6).is_ok());
let _ = Hrmp::prune_hrmp(para_b, 6);
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
});
}
@@ -1732,7 +1855,7 @@ mod tests {
run_to_block(7, Some(vec![6, 7]));
assert!(!Paras::is_valid_para(para_a));
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
});
}
@@ -1791,7 +1914,7 @@ mod tests {
],
);
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
});
}
@@ -1940,7 +2063,7 @@ mod tests {
// The channel should be removed.
assert!(!Paras::is_valid_para(para_a));
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 100);
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 110);
@@ -1978,7 +2101,7 @@ mod tests {
// The outcome we expect is `para_b` should receive the refund.
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 110);
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
});
}
@@ -2007,7 +2130,7 @@ mod tests {
run_to_block(10, Some(vec![10]));
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
Hrmp::assert_storage_consistency_exhaustive();
});
}
}
@@ -0,0 +1,303 @@
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use crate::{
configuration::Pallet as Configuration,
hrmp::{Pallet as Hrmp, *},
paras::Pallet as Paras,
shared::Pallet as Shared,
};
use frame_support::{assert_ok, traits::Currency};
type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
fn register_parachain_with_balance<T: Config>(id: ParaId, balance: BalanceOf<T>) {
assert_ok!(Paras::<T>::initialize_para_now(
id,
crate::paras::ParaGenesisArgs {
parachain: true,
genesis_head: vec![1].into(),
validation_code: vec![1].into(),
},
));
T::Currency::make_free_balance_be(&id.into_account(), balance);
}
fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) {
let events = frame_system::Pallet::<T>::events();
let system_event: <T as frame_system::Config>::Event = generic_event.into();
// compare to the last event record
let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
assert_eq!(event, &system_event);
}
/// Enumerates the phase in the setup process of a channel between two parachains.
enum ParachainSetupStep {
/// A channel open has been requested
Requested,
/// A channel open has been requested and accepted.
Accepted,
/// A channel open has been requested and accepted, and a session has passed and is now open.
Established,
/// A channel open has been requested and accepted, and a session has passed and is now
/// open, and now it has been requested to close down.
CloseRequested,
}
fn establish_para_connection<T: Config>(
from: u32,
to: u32,
until: ParachainSetupStep,
) -> [(ParaId, crate::Origin); 2]
where
<T as frame_system::Config>::Origin: From<crate::Origin>,
{
let config = Configuration::<T>::config();
let deposit: BalanceOf<T> = config.hrmp_sender_deposit.unique_saturated_into();
let capacity = config.hrmp_channel_max_capacity;
let message_size = config.hrmp_channel_max_message_size;
let sender: ParaId = from.into();
let sender_origin: crate::Origin = from.into();
let recipient: ParaId = to.into();
let recipient_origin: crate::Origin = to.into();
let output = [(sender, sender_origin.clone()), (recipient, recipient_origin.clone())];
// Make both a parachain if they are already not.
if !Paras::<T>::is_parachain(sender) {
register_parachain_with_balance::<T>(sender, deposit);
}
if !Paras::<T>::is_parachain(recipient) {
register_parachain_with_balance::<T>(recipient, deposit);
}
assert_ok!(Hrmp::<T>::hrmp_init_open_channel(
sender_origin.clone().into(),
recipient,
capacity,
message_size
));
if matches!(until, ParachainSetupStep::Requested) {
return output
}
assert_ok!(Hrmp::<T>::hrmp_accept_open_channel(recipient_origin.into(), sender));
if matches!(until, ParachainSetupStep::Accepted) {
return output
}
Hrmp::<T>::process_hrmp_open_channel_requests(&Configuration::<T>::config());
if matches!(until, ParachainSetupStep::Established) {
return output
}
let channel_id = HrmpChannelId { sender, recipient };
assert_ok!(Hrmp::<T>::hrmp_close_channel(sender_origin.clone().into(), channel_id));
if matches!(until, ParachainSetupStep::CloseRequested) {
// NOTE: this is just for expressiveness, otherwise the if-statement is 100% useless.
return output
}
output
}
/// Prefix value for account generation. These numbers are used as seeds to create distinct (para)
/// accounts.
///
/// To maintain sensibility created accounts should always be unique and never overlap. For example,
/// if for some benchmarking component `c`, accounts are being created `for s in 0..c` with seed
/// `PREFIX_0 + s`, then we must assert that `c <= PREFIX_1`, meaning that it won't overlap with
/// `PREFIX_2`.
///
/// These values are chosen large enough so that the likelihood of any clash is already very low.
const PREFIX_0: u32 = 10_000;
const PREFIX_1: u32 = PREFIX_0 * 2;
const MAX_UNIQUE_CHANNELS: u32 = 128;
static_assertions::const_assert!(MAX_UNIQUE_CHANNELS < PREFIX_0);
static_assertions::const_assert!(HRMP_MAX_INBOUND_CHANNELS_BOUND < PREFIX_0);
static_assertions::const_assert!(HRMP_MAX_OUTBOUND_CHANNELS_BOUND < PREFIX_0);
frame_benchmarking::benchmarks! {
where_clause { where <T as frame_system::Config>::Origin: From<crate::Origin> }
hrmp_init_open_channel {
let sender_id: ParaId = 1u32.into();
let sender_origin: crate::Origin = 1u32.into();
let recipient_id: ParaId = 2u32.into();
// make sure para is registered, and has enough balance.
let deposit: BalanceOf<T> = Configuration::<T>::config().hrmp_sender_deposit.unique_saturated_into();
register_parachain_with_balance::<T>(sender_id, deposit);
register_parachain_with_balance::<T>(recipient_id, deposit);
let capacity = Configuration::<T>::config().hrmp_channel_max_capacity;
let message_size = Configuration::<T>::config().hrmp_channel_max_message_size;
}: _(sender_origin, recipient_id, capacity, message_size)
verify {
assert_last_event::<T>(
Event::<T>::OpenChannelRequested(sender_id, recipient_id, capacity, message_size).into()
);
}
hrmp_accept_open_channel {
let [(sender, _), (recipient, recipient_origin)] =
establish_para_connection::<T>(1, 2, ParachainSetupStep::Requested);
}: _(recipient_origin, sender)
verify {
assert_last_event::<T>(Event::<T>::OpenChannelAccepted(sender, recipient).into());
}
hrmp_close_channel {
let [(sender, sender_origin), (recipient, _)] =
establish_para_connection::<T>(1, 2, ParachainSetupStep::Established);
let channel_id = HrmpChannelId { sender, recipient };
}: _(sender_origin, channel_id.clone())
verify {
assert_last_event::<T>(Event::<T>::ChannelClosed(sender, channel_id).into());
}
// NOTE: a single parachain should have the maximum number of allowed ingress and egress
// channels.
force_clean_hrmp {
// ingress channels to a single leaving parachain that need to be closed.
let i in 0 .. (HRMP_MAX_INBOUND_CHANNELS_BOUND - 1);
// egress channels to a single leaving parachain that need to be closed.
let e in 0 .. (HRMP_MAX_OUTBOUND_CHANNELS_BOUND - 1);
// first, update the configs to support this many open channels...
assert_ok!(
Configuration::<T>::set_hrmp_max_parachain_outbound_channels(frame_system::RawOrigin::Root.into(), e + 1)
);
assert_ok!(
Configuration::<T>::set_hrmp_max_parachain_inbound_channels(frame_system::RawOrigin::Root.into(), i + 1)
);
// .. and enact it.
Configuration::<T>::initializer_on_new_session(&Shared::<T>::scheduled_session());
let config = Configuration::<T>::config();
let deposit: BalanceOf<T> = config.hrmp_sender_deposit.unique_saturated_into();
let para: ParaId = 1u32.into();
let para_origin: crate::Origin = 1u32.into();
register_parachain_with_balance::<T>(para, deposit);
T::Currency::make_free_balance_be(&para.into_account(), deposit * 256u32.into());
for ingress_para_id in 0..i {
// establish ingress channels to `para`.
let ingress_para_id = ingress_para_id + PREFIX_0;
let _ = establish_para_connection::<T>(ingress_para_id, para.into(), ParachainSetupStep::Established);
}
// nothing should be left unprocessed.
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default(), 0);
for egress_para_id in 0..e {
// establish egress channels to `para`.
let egress_para_id = egress_para_id + PREFIX_1;
let _ = establish_para_connection::<T>(para.into(), egress_para_id, ParachainSetupStep::Established);
}
// nothing should be left unprocessed.
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default(), 0);
// all in all, we have created this many channels.
assert_eq!(HrmpChannels::<T>::iter().count() as u32, i + e);
}: _(frame_system::Origin::<T>::Root, para, i, e) verify {
// all in all, all of them must be gone by now.
assert_eq!(HrmpChannels::<T>::iter().count() as u32, 0);
// borrow this function from the tests to make sure state is clear, given that we do a lot
// of out-of-ordinary ops here.
Hrmp::<T>::assert_storage_consistency_exhaustive();
}
force_process_hrmp_open {
// number of channels that need to be processed. Worse case is an N-M relation: unique
// sender and recipients for all channels.
let c in 0 .. MAX_UNIQUE_CHANNELS;
for id in 0 .. c {
let _ = establish_para_connection::<T>(PREFIX_0 + id, PREFIX_1 + id, ParachainSetupStep::Accepted);
}
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, c);
}: _(frame_system::Origin::<T>::Root, c)
verify {
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, 0);
}
force_process_hrmp_close {
// number of channels that need to be processed. Worse case is an N-M relation: unique
// sender and recipients for all channels.
let c in 0 .. MAX_UNIQUE_CHANNELS;
for id in 0 .. c {
let _ = establish_para_connection::<T>(PREFIX_0 + id, PREFIX_1 + id, ParachainSetupStep::CloseRequested);
}
assert_eq!(HrmpCloseChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, c);
}: _(frame_system::Origin::<T>::Root, c)
verify {
assert_eq!(HrmpCloseChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, 0);
}
hrmp_cancel_open_request {
// number of items already existing in the `HrmpOpenChannelRequestsList`, other than the
// one that we remove.
let c in 0 .. MAX_UNIQUE_CHANNELS;
for id in 0 .. c {
let _ = establish_para_connection::<T>(PREFIX_0 + id, PREFIX_1 + id, ParachainSetupStep::Requested);
}
let [(sender, sender_origin), (recipient, _)] =
establish_para_connection::<T>(1, 2, ParachainSetupStep::Requested);
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, c + 1);
let channel_id = HrmpChannelId { sender, recipient };
}: _(sender_origin, channel_id, c + 1)
verify {
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, c);
}
// worse case will be `n` parachain channel requests, where in all of them either the sender or
// the recipient need to be cleaned. This enforces the deposit of at least one to be processed.
// No code path for triggering two deposit process exists.
clean_open_channel_requests {
let c in 0 .. MAX_UNIQUE_CHANNELS;
for id in 0 .. c {
let _ = establish_para_connection::<T>(PREFIX_0 + id, PREFIX_1 + id, ParachainSetupStep::Requested);
}
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, c);
let outgoing = (0..c).map(|id| (id + PREFIX_1).into()).collect::<Vec<ParaId>>();
let config = Configuration::<T>::config();
}: {
Hrmp::<T>::clean_open_channel_requests(&config, &outgoing);
} verify {
assert_eq!(HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32, 0);
}
}
frame_benchmarking::impl_benchmark_test_suite!(
Hrmp,
crate::mock::new_test_ext(crate::hrmp::tests::GenesisConfigBuilder::default().build()),
crate::mock::Test
);
+5
View File
@@ -236,6 +236,7 @@ impl crate::hrmp::Config for Test {
type Event = Event;
type Origin = Origin;
type Currency = pallet_balances::Pallet<Test>;
type WeightInfo = crate::hrmp::TestWeightInfo;
}
impl crate::disputes::Config for Test {
@@ -363,6 +364,7 @@ impl UmpSink for TestUmpSink {
let id = sp_io::hashing::blake2_256(actual_msg);
return Err((id, weight))
}
PROCESSED.with(|opt_hook| {
opt_hook.borrow_mut().push((actual_origin, actual_msg.to_owned()));
});
@@ -395,6 +397,9 @@ impl inclusion::RewardValidators for TestRewardValidators {
pub fn new_test_ext(state: MockGenesisConfig) -> TestExternalities {
use sp_keystore::{testing::KeyStore, KeystoreExt, SyncCryptoStorePtr};
use sp_std::sync::Arc;
sp_tracing::try_init_simple();
BACKING_REWARDS.with(|r| r.borrow_mut().clear());
AVAILABILITY_REWARDS.with(|r| r.borrow_mut().clear());
@@ -1993,4 +1993,20 @@ impl<T: Config> Pallet<T> {
pub fn heads_insert(para_id: &ParaId, head_data: HeadData) {
Heads::<T>::insert(para_id, head_data);
}
#[cfg(feature = "runtime-benchmarks")]
pub(crate) fn initialize_para_now(id: ParaId, genesis: ParaGenesisArgs) -> DispatchResult {
// first queue this para actions..
let _ = Self::schedule_para_initialize(id, genesis)?;
// .. and immediately apply them.
Self::apply_actions_queue(Self::scheduled_session());
// ensure it has become a para.
ensure!(
ParaLifecycles::<T>::get(id) == Some(ParaLifecycle::Parachain),
"Parachain not created properly"
);
Ok(())
}
}
+1
View File
@@ -1218,6 +1218,7 @@ impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo<Self>;
}
impl parachains_paras_inherent::Config for Runtime {
@@ -45,6 +45,7 @@ pub mod runtime_common_crowdloan;
pub mod runtime_common_paras_registrar;
pub mod runtime_common_slots;
pub mod runtime_parachains_configuration;
pub mod runtime_parachains_hrmp;
pub mod runtime_parachains_initializer;
pub mod runtime_parachains_paras;
pub mod runtime_parachains_paras_inherent;
@@ -0,0 +1,157 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `runtime_parachains::hrmp`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2021-11-05, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 128
// Executed Command:
// target/release/polkadot
// benchmark
// --chain=kusama-dev
// --steps=50
// --repeat=20
// --pallet=runtime_parachains::hrmp
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/kusama/src/weights/runtime_parachains_hrmp.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::Weight};
use sp_std::marker::PhantomData;
/// Weight functions for `runtime_parachains::hrmp`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInfo<T> {
// Storage: Paras ParaLifecycles (r:2 w:0)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_init_open_channel() -> Weight {
(54_952_000 as Weight)
.saturating_add(T::DbWeight::get().reads(10 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Paras ParaLifecycles (r:1 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_accept_open_channel() -> Weight {
(47_965_000 as Weight)
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_close_channel() -> Weight {
(44_369_000 as Weight)
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:127 w:127)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1)
// Storage: Hrmp HrmpChannelContents (r:0 w:127)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1)
fn force_clean_hrmp(i: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 17_000
.saturating_add((15_959_000 as Weight).saturating_mul(i as Weight))
// Standard Error: 17_000
.saturating_add((16_048_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(e as Weight)))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(e as Weight)))
}
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
// Storage: Paras ParaLifecycles (r:4 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpChannels (r:0 w:2)
fn force_process_hrmp_open(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 26_000
.saturating_add((35_598_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((7 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((6 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpChannels (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:2)
// Storage: Hrmp HrmpChannelContents (r:0 w:2)
fn force_process_hrmp_close(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 15_000
.saturating_add((20_510_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((5 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
fn hrmp_cancel_open_request(c: u32, ) -> Weight {
(32_749_000 as Weight)
// Standard Error: 0
.saturating_add((59_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
fn clean_open_channel_requests(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 6_000
.saturating_add((5_781_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight)))
}
}
+2 -1
View File
@@ -596,7 +596,7 @@ impl pallet_authorship::Config for Runtime {
impl parachains_origin::Config for Runtime {}
impl parachains_configuration::Config for Runtime {
type WeightInfo = weights::runtime_parachains_configuration::WeightInfo<Runtime>;
type WeightInfo = parachains_configuration::TestWeightInfo;
}
impl parachains_shared::Config for Runtime {}
@@ -645,6 +645,7 @@ impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo<Self>;
}
impl parachains_paras_inherent::Config for Runtime {
@@ -17,5 +17,6 @@
pub mod runtime_parachains_configuration;
pub mod runtime_parachains_disputes;
pub mod runtime_parachains_hrmp;
pub mod runtime_parachains_paras;
pub mod runtime_parachains_paras_inherent;
@@ -0,0 +1,157 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `runtime_parachains::hrmp`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2021-11-05, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 128
// Executed Command:
// target/release/polkadot
// benchmark
// --chain=kusama-dev
// --steps=50
// --repeat=20
// --pallet=runtime_parachains::hrmp
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/kusama/src/weights/runtime_parachains_hrmp.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::Weight};
use sp_std::marker::PhantomData;
/// Weight functions for `runtime_parachains::hrmp`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInfo<T> {
// Storage: Paras ParaLifecycles (r:2 w:0)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_init_open_channel() -> Weight {
(54_952_000 as Weight)
.saturating_add(T::DbWeight::get().reads(10 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Paras ParaLifecycles (r:1 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_accept_open_channel() -> Weight {
(47_965_000 as Weight)
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1)
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_close_channel() -> Weight {
(44_369_000 as Weight)
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:127 w:127)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1)
// Storage: Hrmp HrmpChannelContents (r:0 w:127)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1)
fn force_clean_hrmp(i: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 17_000
.saturating_add((15_959_000 as Weight).saturating_mul(i as Weight))
// Standard Error: 17_000
.saturating_add((16_048_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(e as Weight)))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(e as Weight)))
}
// Storage: Configuration ActiveConfig (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
// Storage: Paras ParaLifecycles (r:4 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpChannels (r:0 w:2)
fn force_process_hrmp_open(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 26_000
.saturating_add((35_598_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((7 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((6 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpChannels (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:2)
// Storage: Hrmp HrmpChannelContents (r:0 w:2)
fn force_process_hrmp_close(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 15_000
.saturating_add((20_510_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((5 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
fn hrmp_cancel_open_request(c: u32, ) -> Weight {
(32_749_000 as Weight)
// Standard Error: 0
.saturating_add((59_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
fn clean_open_channel_requests(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 6_000
.saturating_add((5_781_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight)))
}
}
+1
View File
@@ -549,6 +549,7 @@ impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type WeightInfo = parachains_hrmp::TestWeightInfo;
}
impl parachains_scheduler::Config for Runtime {}
+3
View File
@@ -858,6 +858,7 @@ impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo<Self>;
}
impl parachains_paras_inherent::Config for Runtime {
@@ -1479,6 +1480,7 @@ sp_api::impl_runtime_apis! {
list_benchmark!(list, extra, runtime_common::paras_registrar, Registrar);
list_benchmark!(list, extra, runtime_common::slots, Slots);
list_benchmark!(list, extra, runtime_parachains::configuration, Configuration);
list_benchmark!(list, extra, runtime_parachains::hrmp, Hrmp);
list_benchmark!(list, extra, runtime_parachains::initializer, Initializer);
list_benchmark!(list, extra, runtime_parachains::paras_inherent, ParaInherent);
list_benchmark!(list, extra, runtime_parachains::paras, Paras);
@@ -1629,6 +1631,7 @@ sp_api::impl_runtime_apis! {
add_benchmark!(params, batches, runtime_common::paras_registrar, Registrar);
add_benchmark!(params, batches, runtime_common::slots, Slots);
add_benchmark!(params, batches, runtime_parachains::configuration, Configuration);
add_benchmark!(params, batches, runtime_parachains::hrmp, Hrmp);
add_benchmark!(params, batches, runtime_parachains::initializer, Initializer);
add_benchmark!(params, batches, runtime_parachains::paras, Paras);
add_benchmark!(params, batches, runtime_parachains::paras_inherent, ParaInherent);
@@ -36,6 +36,7 @@ pub mod runtime_common_crowdloan;
pub mod runtime_common_paras_registrar;
pub mod runtime_common_slots;
pub mod runtime_parachains_configuration;
pub mod runtime_parachains_hrmp;
pub mod runtime_parachains_initializer;
pub mod runtime_parachains_paras;
pub mod runtime_parachains_paras_inherent;
@@ -0,0 +1,153 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `runtime_parachains::hrmp`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2021-11-05, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 128
// Executed Command:
// target/release/polkadot
// benchmark
// --chain=westend-dev
// --steps=50
// --repeat=20
// --pallet=runtime_parachains::hrmp
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/westend/src/weights/runtime_parachains_hrmp.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::Weight};
use sp_std::marker::PhantomData;
/// Weight functions for `runtime_parachains::hrmp`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInfo<T> {
// Storage: Paras ParaLifecycles (r:2 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_init_open_channel() -> Weight {
(55_142_000 as Weight)
.saturating_add(T::DbWeight::get().reads(9 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Paras ParaLifecycles (r:1 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_accept_open_channel() -> Weight {
(47_170_000 as Weight)
.saturating_add(T::DbWeight::get().reads(6 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpChannels (r:1 w:0)
// Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1)
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
fn hrmp_close_channel() -> Weight {
(43_586_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
// Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127)
// Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1)
// Storage: Hrmp HrmpChannels (r:127 w:127)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1)
// Storage: Hrmp HrmpChannelContents (r:0 w:127)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1)
fn force_clean_hrmp(i: u32, e: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 21_000
.saturating_add((15_726_000 as Weight).saturating_mul(i as Weight))
// Standard Error: 21_000
.saturating_add((15_859_000 as Weight).saturating_mul(e as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(e as Weight)))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(i as Weight)))
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(e as Weight)))
}
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
// Storage: Paras ParaLifecycles (r:4 w:0)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:2 w:2)
// Storage: Hrmp HrmpChannels (r:0 w:2)
fn force_process_hrmp_open(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 24_000
.saturating_add((35_104_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((7 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((6 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0)
// Storage: Hrmp HrmpChannels (r:2 w:2)
// Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2)
// Storage: Hrmp HrmpCloseChannelRequests (r:0 w:2)
// Storage: Hrmp HrmpChannelContents (r:0 w:2)
fn force_process_hrmp_close(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 14_000
.saturating_add((20_295_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((5 as Weight).saturating_mul(c as Weight)))
}
// Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1)
fn hrmp_cancel_open_request(c: u32, ) -> Weight {
(32_796_000 as Weight)
// Standard Error: 0
.saturating_add((58_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
// Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1)
// Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2)
fn clean_open_channel_requests(c: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 6_000
.saturating_add((5_748_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(c as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight)))
}
}