Remove bridges subtree

This commit is contained in:
Serban Iorga
2024-04-09 16:02:09 +03:00
committed by Bastian Köcher
parent d38f6e6728
commit 9a3e2c8c5a
179 changed files with 0 additions and 34372 deletions
-71
View File
@@ -1,71 +0,0 @@
[package]
name = "pallet-bridge-parachains"
version = "0.7.0"
description = "Module that allows bridged relay chains to exchange information on their parachains' heads."
authors.workspace = true
edition.workspace = true
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
repository.workspace = true
[lints]
workspace = true
[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false }
log = { workspace = true }
scale-info = { version = "2.11.1", default-features = false, features = ["derive"] }
# Bridge Dependencies
bp-header-chain = { path = "../../primitives/header-chain", default-features = false }
bp-parachains = { path = "../../primitives/parachains", default-features = false }
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
bp-runtime = { path = "../../primitives/runtime", default-features = false }
pallet-bridge-grandpa = { path = "../grandpa", default-features = false }
# Substrate Dependencies
frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true }
frame-support = { path = "../../../substrate/frame/support", default-features = false }
frame-system = { path = "../../../substrate/frame/system", default-features = false }
sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false }
sp-std = { path = "../../../substrate/primitives/std", default-features = false }
sp-trie = { path = "../../../substrate/primitives/trie", default-features = false }
[dev-dependencies]
bp-header-chain = { path = "../../primitives/header-chain" }
bp-test-utils = { path = "../../primitives/test-utils" }
sp-core = { path = "../../../substrate/primitives/core" }
sp-io = { path = "../../../substrate/primitives/io" }
[features]
default = ["std"]
std = [
"bp-header-chain/std",
"bp-parachains/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"codec/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-bridge-grandpa/std",
"scale-info/std",
"sp-runtime/std",
"sp-std/std",
"sp-trie/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-bridge-grandpa/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-bridge-grandpa/try-runtime",
"sp-runtime/try-runtime",
]
-90
View File
@@ -1,90 +0,0 @@
# Bridge Parachains Pallet
The bridge parachains pallet is a light client for one or several parachains of the bridged relay chain.
It serves as a source of finalized parachain headers and is used when you need to build a bridge with
a parachain.
The pallet requires [bridge GRANDPA pallet](../grandpa/) to be deployed at the same chain - it is used
to verify storage proofs, generated at the bridged relay chain.
## A Brief Introduction into Parachains Finality
You can find detailed information on parachains finality in the
[Polkadot-SDK](https://github.com/paritytech/polkadot-sdk) repository. This section gives a brief overview of how the
parachain finality works and how to build a light client for a parachain.
The main thing there is that the parachain generates blocks on its own, but it can't achieve finality without
help of its relay chain. Instead, the parachain collators create a block and hand it over to the relay chain
validators. Validators validate the block and register the new parachain head in the
[`Heads` map](https://github.com/paritytech/polkadot-sdk/blob/bc5005217a8c2e7c95b9011c96d7e619879b1200/polkadot/runtime/parachains/src/paras/mod.rs#L683-L686)
of the [`paras`](https://github.com/paritytech/polkadot-sdk/tree/master/polkadot/runtime/parachains/src/paras) pallet,
deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet,
even though the names are similar.
And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that
`Heads` map. It does that using relay chain header, that has been previously imported by the
[bridge GRANDPA pallet](../grandpa/). Once the proof is verified, the pallet knows that the given parachain
header has been finalized by the relay chain. The parachain header fields may then be used to verify storage
proofs, coming from the parachain. This allows the pallet to be used e.g. as a source of finality for the messages
pallet.
## Pallet Operations
The main entrypoint of the pallet is the `submit_parachain_heads` call. It has three arguments:
- storage proof of parachain heads from the `Heads` map;
- parachain identifiers and hashes of their heads from the storage proof;
- the relay block, at which the storage proof has been generated.
The pallet may track multiple parachains. And the parachains may use different primitives - one may use 128-bit block
numbers, other - 32-bit. To avoid extra decode operations, the pallet is using relay chain block number to order
parachain headers. Any finalized descendant of finalized relay block `RB`, which has parachain block `PB` in
its `Heads` map, is guaranteed to have either `PB`, or its descendant. So parachain block number grows with relay
block number.
The pallet may reject parachain head if it already knows better (or the same) head. In addition, pallet rejects
heads of untracked parachains.
The pallet doesn't track anything behind parachain heads. So it requires no initialization - it is ready to accept
headers right after deployment.
## Non-Essential Functionality
There may be a special account in every runtime where the bridge parachains module is deployed. This
account, named 'module owner', is like a module-level sudo account - he's able to halt and
resume all module operations without requiring runtime upgrade. Calls that are related to this
account are:
- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account;
- `fn set_operating_mode()`: the module owner (or sudo account) may call this function to stop all
module operations. After this call, all finality proofs will be rejected until further `set_operating_mode` call'.
This call may be used when something extraordinary happens with the bridge.
If pallet owner is not defined, the governance may be used to make those calls.
## Signed Extension to Reject Obsolete Headers
It'd be better for anyone (for chain and for submitters) to reject all transactions that are submitting
already known parachain heads to the pallet. This way, we leave block space to other useful transactions and
we don't charge concurrent submitters for their honest actions.
To deal with that, we have a [signed extension](./src/call_ext) that may be added to the runtime.
It does exactly what is required - rejects all transactions with already known heads. The submitter
pays nothing for such transactions - they're simply removed from the transaction pool, when the block
is built.
The signed extension, however, is a bit limited - it only works with transactions that provide single
parachain head. So it won't work with multiple parachain heads transactions. This fits our needs
for [Kusama <> Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md). If you need to deal
with other transaction formats, you may implement similar extension for your runtime.
You may also take a look at the [`generate_bridge_reject_obsolete_headers_and_messages`](../../bin/runtime-common/src/lib.rs)
macro that bundles several similar signed extensions in a single one.
## Parachains Finality Relay
We have an offchain actor, who is watching for new parachain heads and submits them to the bridged chain.
It is the parachains relay - you may look at the [crate level documentation and the code](../../relays/parachains/).
@@ -1,116 +0,0 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Parachains finality pallet benchmarking.
use crate::{
weights_ext::DEFAULT_PARACHAIN_HEAD_SIZE, Call, RelayBlockHash, RelayBlockHasher,
RelayBlockNumber,
};
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use bp_runtime::StorageProofSize;
use frame_benchmarking::{account, benchmarks_instance_pallet};
use frame_system::RawOrigin;
use sp_std::prelude::*;
/// Pallet we're benchmarking here.
pub struct Pallet<T: Config<I>, I: 'static = ()>(crate::Pallet<T, I>);
/// Trait that must be implemented by runtime to benchmark the parachains finality pallet.
pub trait Config<I: 'static>: crate::Config<I> {
/// Returns vector of supported parachains.
fn parachains() -> Vec<ParaId>;
/// Generate parachain heads proof and prepare environment for verifying this proof.
fn prepare_parachain_heads_proof(
parachains: &[ParaId],
parachain_head_size: u32,
proof_size: StorageProofSize,
) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof, Vec<(ParaId, ParaHash)>);
}
benchmarks_instance_pallet! {
where_clause {
where
<T as pallet_bridge_grandpa::Config<T::BridgesGrandpaPalletInstance>>::BridgedChain:
bp_runtime::Chain<
BlockNumber = RelayBlockNumber,
Hash = RelayBlockHash,
Hasher = RelayBlockHasher,
>,
}
// Benchmark `submit_parachain_heads` extrinsic with different number of parachains.
submit_parachain_heads_with_n_parachains {
let p in 1..(T::parachains().len() + 1) as u32;
let sender = account("sender", 0, 0);
let mut parachains = T::parachains();
let _ = if p <= parachains.len() as u32 {
parachains.split_off(p as usize)
} else {
Default::default()
};
log::trace!(target: crate::LOG_TARGET, "=== {:?}", parachains.len());
let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof(
&parachains,
DEFAULT_PARACHAIN_HEAD_SIZE,
StorageProofSize::Minimal(0),
);
let at_relay_block = (relay_block_number, relay_block_hash);
}: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof)
verify {
for parachain in parachains {
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
}
}
// Benchmark `submit_parachain_heads` extrinsic with 1kb proof size.
submit_parachain_heads_with_1kb_proof {
let sender = account("sender", 0, 0);
let parachains = vec![T::parachains()[0]];
let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof(
&parachains,
DEFAULT_PARACHAIN_HEAD_SIZE,
StorageProofSize::HasLargeLeaf(1024),
);
let at_relay_block = (relay_block_number, relay_block_hash);
}: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof)
verify {
for parachain in parachains {
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
}
}
// Benchmark `submit_parachain_heads` extrinsic with 16kb proof size.
submit_parachain_heads_with_16kb_proof {
let sender = account("sender", 0, 0);
let parachains = vec![T::parachains()[0]];
let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof(
&parachains,
DEFAULT_PARACHAIN_HEAD_SIZE,
StorageProofSize::HasLargeLeaf(16 * 1024),
);
let at_relay_block = (relay_block_number, relay_block_hash);
}: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof)
verify {
for parachain in parachains {
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
}
}
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime)
}
-263
View File
@@ -1,263 +0,0 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::{Config, Pallet, RelayBlockNumber};
use bp_parachains::BestParaHeadHash;
use bp_polkadot_core::parachains::{ParaHash, ParaId};
use bp_runtime::OwnedBridgeModule;
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
use sp_runtime::{
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
RuntimeDebug,
};
/// Info about a `SubmitParachainHeads` call which tries to update a single parachain.
#[derive(PartialEq, RuntimeDebug)]
pub struct SubmitParachainHeadsInfo {
/// Number of the finalized relay block that has been used to prove parachain finality.
pub at_relay_block_number: RelayBlockNumber,
/// Parachain identifier.
pub para_id: ParaId,
/// Hash of the bundled parachain head.
pub para_head_hash: ParaHash,
}
/// Helper struct that provides methods for working with the `SubmitParachainHeads` call.
pub struct SubmitParachainHeadsHelper<T: Config<I>, I: 'static> {
_phantom_data: sp_std::marker::PhantomData<(T, I)>,
}
impl<T: Config<I>, I: 'static> SubmitParachainHeadsHelper<T, I> {
/// Check if the para head provided by the `SubmitParachainHeads` is better than the best one
/// we know.
pub fn is_obsolete(update: &SubmitParachainHeadsInfo) -> bool {
let stored_best_head = match crate::ParasInfo::<T, I>::get(update.para_id) {
Some(stored_best_head) => stored_best_head,
None => return false,
};
if stored_best_head.best_head_hash.at_relay_block_number >= update.at_relay_block_number {
log::trace!(
target: crate::LOG_TARGET,
"The parachain head can't be updated. The parachain head for {:?} \
was already updated at better relay chain block {} >= {}.",
update.para_id,
stored_best_head.best_head_hash.at_relay_block_number,
update.at_relay_block_number
);
return true
}
if stored_best_head.best_head_hash.head_hash == update.para_head_hash {
log::trace!(
target: crate::LOG_TARGET,
"The parachain head can't be updated. The parachain head hash for {:?} \
was already updated to {} at block {} < {}.",
update.para_id,
update.para_head_hash,
stored_best_head.best_head_hash.at_relay_block_number,
update.at_relay_block_number
);
return true
}
false
}
/// Check if the `SubmitParachainHeads` was successfully executed.
pub fn was_successful(update: &SubmitParachainHeadsInfo) -> bool {
match crate::ParasInfo::<T, I>::get(update.para_id) {
Some(stored_best_head) =>
stored_best_head.best_head_hash ==
BestParaHeadHash {
at_relay_block_number: update.at_relay_block_number,
head_hash: update.para_head_hash,
},
None => false,
}
}
}
/// Trait representing a call that is a sub type of this pallet's call.
pub trait CallSubType<T: Config<I, RuntimeCall = Self>, I: 'static>:
IsSubType<CallableCallFor<Pallet<T, I>, T>>
{
/// Create a new instance of `SubmitParachainHeadsInfo` from a `SubmitParachainHeads` call with
/// one single parachain entry.
fn one_entry_submit_parachain_heads_info(&self) -> Option<SubmitParachainHeadsInfo> {
if let Some(crate::Call::<T, I>::submit_parachain_heads {
ref at_relay_block,
ref parachains,
..
}) = self.is_sub_type()
{
if let &[(para_id, para_head_hash)] = parachains.as_slice() {
return Some(SubmitParachainHeadsInfo {
at_relay_block_number: at_relay_block.0,
para_id,
para_head_hash,
})
}
}
None
}
/// Create a new instance of `SubmitParachainHeadsInfo` from a `SubmitParachainHeads` call with
/// one single parachain entry, if the entry is for the provided parachain id.
fn submit_parachain_heads_info_for(&self, para_id: u32) -> Option<SubmitParachainHeadsInfo> {
self.one_entry_submit_parachain_heads_info()
.filter(|update| update.para_id.0 == para_id)
}
/// Validate parachain heads in order to avoid "mining" transactions that provide
/// outdated bridged parachain heads. Without this validation, even honest relayers
/// may lose their funds if there are multiple relays running and submitting the
/// same information.
///
/// This validation only works with transactions that are updating single parachain
/// head. We can't use unbounded validation - it may take too long and either break
/// block production, or "eat" significant portion of block production time literally
/// for nothing. In addition, the single-parachain-head-per-transaction is how the
/// pallet will be used in our environment.
fn check_obsolete_submit_parachain_heads(&self) -> TransactionValidity
where
Self: Sized,
{
let update = match self.one_entry_submit_parachain_heads_info() {
Some(update) => update,
None => return Ok(ValidTransaction::default()),
};
if Pallet::<T, I>::ensure_not_halted().is_err() {
return InvalidTransaction::Call.into()
}
if SubmitParachainHeadsHelper::<T, I>::is_obsolete(&update) {
return InvalidTransaction::Stale.into()
}
Ok(ValidTransaction::default())
}
}
impl<T, I: 'static> CallSubType<T, I> for T::RuntimeCall
where
T: Config<I>,
T::RuntimeCall: IsSubType<CallableCallFor<Pallet<T, I>, T>>,
{
}
#[cfg(test)]
mod tests {
use crate::{
mock::{run_test, RuntimeCall, TestRuntime},
CallSubType, PalletOperatingMode, ParaInfo, ParasInfo, RelayBlockNumber,
};
use bp_parachains::BestParaHeadHash;
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use bp_runtime::BasicOperatingMode;
fn validate_submit_parachain_heads(
num: RelayBlockNumber,
parachains: Vec<(ParaId, ParaHash)>,
) -> bool {
RuntimeCall::Parachains(crate::Call::<TestRuntime, ()>::submit_parachain_heads {
at_relay_block: (num, Default::default()),
parachains,
parachain_heads_proof: ParaHeadsProof { storage_proof: Vec::new() },
})
.check_obsolete_submit_parachain_heads()
.is_ok()
}
fn sync_to_relay_header_10() {
ParasInfo::<TestRuntime, ()>::insert(
ParaId(1),
ParaInfo {
best_head_hash: BestParaHeadHash {
at_relay_block_number: 10,
head_hash: [1u8; 32].into(),
},
next_imported_hash_position: 0,
},
);
}
#[test]
fn extension_rejects_header_from_the_obsolete_relay_block() {
run_test(|| {
// when current best finalized is #10 and we're trying to import header#5 => tx is
// rejected
sync_to_relay_header_10();
assert!(!validate_submit_parachain_heads(5, vec![(ParaId(1), [1u8; 32].into())]));
});
}
#[test]
fn extension_rejects_header_from_the_same_relay_block() {
run_test(|| {
// when current best finalized is #10 and we're trying to import header#10 => tx is
// rejected
sync_to_relay_header_10();
assert!(!validate_submit_parachain_heads(10, vec![(ParaId(1), [1u8; 32].into())]));
});
}
#[test]
fn extension_rejects_header_from_new_relay_block_with_same_hash() {
run_test(|| {
// when current best finalized is #10 and we're trying to import header#10 => tx is
// rejected
sync_to_relay_header_10();
assert!(!validate_submit_parachain_heads(20, vec![(ParaId(1), [1u8; 32].into())]));
});
}
#[test]
fn extension_rejects_header_if_pallet_is_halted() {
run_test(|| {
// when pallet is halted => tx is rejected
sync_to_relay_header_10();
PalletOperatingMode::<TestRuntime, ()>::put(BasicOperatingMode::Halted);
assert!(!validate_submit_parachain_heads(15, vec![(ParaId(1), [2u8; 32].into())]));
});
}
#[test]
fn extension_accepts_new_header() {
run_test(|| {
// when current best finalized is #10 and we're trying to import header#15 => tx is
// accepted
sync_to_relay_header_10();
assert!(validate_submit_parachain_heads(15, vec![(ParaId(1), [2u8; 32].into())]));
});
}
#[test]
fn extension_accepts_if_more_than_one_parachain_is_submitted() {
run_test(|| {
// when current best finalized is #10 and we're trying to import header#5, but another
// parachain head is also supplied => tx is accepted
sync_to_relay_header_10();
assert!(validate_submit_parachain_heads(
5,
vec![(ParaId(1), [1u8; 32].into()), (ParaId(2), [1u8; 32].into())]
));
});
}
}
File diff suppressed because it is too large Load Diff
-328
View File
@@ -1,328 +0,0 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use bp_header_chain::ChainWithGrandpa;
use bp_polkadot_core::parachains::ParaId;
use bp_runtime::{Chain, ChainId, Parachain};
use frame_support::{
construct_runtime, derive_impl, parameter_types, traits::ConstU32, weights::Weight,
};
use sp_runtime::{
testing::H256,
traits::{BlakeTwo256, Header as HeaderT},
MultiSignature,
};
use crate as pallet_bridge_parachains;
pub type AccountId = u64;
pub type RelayBlockHeader =
sp_runtime::generic::Header<crate::RelayBlockNumber, crate::RelayBlockHasher>;
type Block = frame_system::mocking::MockBlock<TestRuntime>;
pub const PARAS_PALLET_NAME: &str = "Paras";
pub const UNTRACKED_PARACHAIN_ID: u32 = 10;
// use exact expected encoded size: `vec_len_size + header_number_size + state_root_hash_size`
pub const MAXIMAL_PARACHAIN_HEAD_DATA_SIZE: u32 = 1 + 8 + 32;
// total parachains that we use in tests
pub const TOTAL_PARACHAINS: u32 = 4;
pub type RegularParachainHeader = sp_runtime::testing::Header;
pub type RegularParachainHasher = BlakeTwo256;
pub type BigParachainHeader = sp_runtime::generic::Header<u128, BlakeTwo256>;
pub struct Parachain1;
impl Chain for Parachain1 {
const ID: ChainId = *b"pch1";
type BlockNumber = u64;
type Hash = H256;
type Hasher = RegularParachainHasher;
type Header = RegularParachainHeader;
type AccountId = u64;
type Balance = u64;
type Nonce = u64;
type Signature = MultiSignature;
fn max_extrinsic_size() -> u32 {
0
}
fn max_extrinsic_weight() -> Weight {
Weight::zero()
}
}
impl Parachain for Parachain1 {
const PARACHAIN_ID: u32 = 1;
}
pub struct Parachain2;
impl Chain for Parachain2 {
const ID: ChainId = *b"pch2";
type BlockNumber = u64;
type Hash = H256;
type Hasher = RegularParachainHasher;
type Header = RegularParachainHeader;
type AccountId = u64;
type Balance = u64;
type Nonce = u64;
type Signature = MultiSignature;
fn max_extrinsic_size() -> u32 {
0
}
fn max_extrinsic_weight() -> Weight {
Weight::zero()
}
}
impl Parachain for Parachain2 {
const PARACHAIN_ID: u32 = 2;
}
pub struct Parachain3;
impl Chain for Parachain3 {
const ID: ChainId = *b"pch3";
type BlockNumber = u64;
type Hash = H256;
type Hasher = RegularParachainHasher;
type Header = RegularParachainHeader;
type AccountId = u64;
type Balance = u64;
type Nonce = u64;
type Signature = MultiSignature;
fn max_extrinsic_size() -> u32 {
0
}
fn max_extrinsic_weight() -> Weight {
Weight::zero()
}
}
impl Parachain for Parachain3 {
const PARACHAIN_ID: u32 = 3;
}
// this parachain is using u128 as block number and stored head data size exceeds limit
pub struct BigParachain;
impl Chain for BigParachain {
const ID: ChainId = *b"bpch";
type BlockNumber = u128;
type Hash = H256;
type Hasher = RegularParachainHasher;
type Header = BigParachainHeader;
type AccountId = u64;
type Balance = u64;
type Nonce = u64;
type Signature = MultiSignature;
fn max_extrinsic_size() -> u32 {
0
}
fn max_extrinsic_weight() -> Weight {
Weight::zero()
}
}
impl Parachain for BigParachain {
const PARACHAIN_ID: u32 = 4;
}
construct_runtime! {
pub enum TestRuntime
{
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
Grandpa1: pallet_bridge_grandpa::<Instance1>::{Pallet, Event<T>},
Grandpa2: pallet_bridge_grandpa::<Instance2>::{Pallet, Event<T>},
Parachains: pallet_bridge_parachains::{Call, Pallet, Event<T>},
}
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Block = Block;
}
parameter_types! {
pub const HeadersToKeep: u32 = 5;
}
impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance1> for TestRuntime {
type RuntimeEvent = RuntimeEvent;
type BridgedChain = TestBridgedChain;
type MaxFreeMandatoryHeadersPerBlock = ConstU32<2>;
type HeadersToKeep = HeadersToKeep;
type WeightInfo = ();
}
impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance2> for TestRuntime {
type RuntimeEvent = RuntimeEvent;
type BridgedChain = TestBridgedChain;
type MaxFreeMandatoryHeadersPerBlock = ConstU32<2>;
type HeadersToKeep = HeadersToKeep;
type WeightInfo = ();
}
parameter_types! {
pub const HeadsToKeep: u32 = 4;
pub const ParasPalletName: &'static str = PARAS_PALLET_NAME;
pub GetTenFirstParachains: Vec<ParaId> = (0..10).map(ParaId).collect();
}
impl pallet_bridge_parachains::Config for TestRuntime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
type ParasPalletName = ParasPalletName;
type ParaStoredHeaderDataBuilder = (Parachain1, Parachain2, Parachain3, BigParachain);
type HeadsToKeep = HeadsToKeep;
type MaxParaHeadDataSize = ConstU32<MAXIMAL_PARACHAIN_HEAD_DATA_SIZE>;
}
#[cfg(feature = "runtime-benchmarks")]
impl pallet_bridge_parachains::benchmarking::Config<()> for TestRuntime {
fn parachains() -> Vec<ParaId> {
vec![
ParaId(Parachain1::PARACHAIN_ID),
ParaId(Parachain2::PARACHAIN_ID),
ParaId(Parachain3::PARACHAIN_ID),
]
}
fn prepare_parachain_heads_proof(
parachains: &[ParaId],
_parachain_head_size: u32,
_proof_size: bp_runtime::StorageProofSize,
) -> (
crate::RelayBlockNumber,
crate::RelayBlockHash,
bp_polkadot_core::parachains::ParaHeadsProof,
Vec<(ParaId, bp_polkadot_core::parachains::ParaHash)>,
) {
// in mock run we only care about benchmarks correctness, not the benchmark results
// => ignore size related arguments
let (state_root, proof, parachains) =
bp_test_utils::prepare_parachain_heads_proof::<RegularParachainHeader>(
parachains.iter().map(|p| (p.0, crate::tests::head_data(p.0, 1))).collect(),
);
let relay_genesis_hash = crate::tests::initialize(state_root);
(0, relay_genesis_hash, proof, parachains)
}
}
#[derive(Debug)]
pub struct TestBridgedChain;
impl Chain for TestBridgedChain {
const ID: ChainId = *b"tbch";
type BlockNumber = crate::RelayBlockNumber;
type Hash = crate::RelayBlockHash;
type Hasher = crate::RelayBlockHasher;
type Header = RelayBlockHeader;
type AccountId = AccountId;
type Balance = u32;
type Nonce = u32;
type Signature = sp_runtime::testing::TestSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
}
impl ChainWithGrandpa for TestBridgedChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
const MAX_AUTHORITIES_COUNT: u32 = 16;
const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8;
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE: u32 = 64;
}
#[derive(Debug)]
pub struct OtherBridgedChain;
impl Chain for OtherBridgedChain {
const ID: ChainId = *b"obch";
type BlockNumber = u64;
type Hash = crate::RelayBlockHash;
type Hasher = crate::RelayBlockHasher;
type Header = sp_runtime::generic::Header<u64, crate::RelayBlockHasher>;
type AccountId = AccountId;
type Balance = u32;
type Nonce = u32;
type Signature = sp_runtime::testing::TestSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
}
impl ChainWithGrandpa for OtherBridgedChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
const MAX_AUTHORITIES_COUNT: u32 = 16;
const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8;
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE: u32 = 64;
}
/// Return test externalities to use in tests.
pub fn new_test_ext() -> sp_io::TestExternalities {
sp_io::TestExternalities::new(Default::default())
}
/// Run pallet test.
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
new_test_ext().execute_with(|| {
System::set_block_number(1);
System::reset_events();
test()
})
}
/// Return test relay chain header with given number.
pub fn test_relay_header(
num: crate::RelayBlockNumber,
state_root: crate::RelayBlockHash,
) -> RelayBlockHeader {
RelayBlockHeader::new(
num,
Default::default(),
state_root,
Default::default(),
Default::default(),
)
}
-273
View File
@@ -1,273 +0,0 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for pallet_bridge_parachains
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
// Executed Command:
// target/release/unknown-bridge-node
// benchmark
// pallet
// --chain=dev
// --steps=50
// --repeat=20
// --pallet=pallet_bridge_parachains
// --extrinsic=*
// --execution=wasm
// --wasm-execution=Compiled
// --heap-pages=4096
// --output=./modules/parachains/src/weights.rs
// --template=./.maintain/bridge-weight-template.hbs
#![allow(clippy::all)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{
traits::Get,
weights::{constants::RocksDbWeight, Weight},
};
use sp_std::marker::PhantomData;
/// Weight functions needed for pallet_bridge_parachains.
pub trait WeightInfo {
fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight;
fn submit_parachain_heads_with_1kb_proof() -> Weight;
fn submit_parachain_heads_with_16kb_proof() -> Weight;
}
/// Weights for `pallet_bridge_parachains` that are generated using one of the Bridge testnets.
///
/// Those weights are test only and must never be used in production.
pub struct BridgeWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for BridgeWeight<T> {
/// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0)
///
/// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1),
/// added: 496, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0)
///
/// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
/// added: 2048, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added:
/// 555, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size:
/// Some(64), added: 1549, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size:
/// Some(196), added: 1681, mode: MaxEncodedLen)
///
/// The range of component `p` is `[1, 2]`.
fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight {
// Proof Size summary in bytes:
// Measured: `366`
// Estimated: `4648`
// Minimum execution time: 36_701 nanoseconds.
Weight::from_parts(38_597_828, 4648)
// Standard Error: 190_859
.saturating_add(Weight::from_parts(60_685, 0).saturating_mul(p.into()))
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(3_u64))
}
/// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0)
///
/// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1),
/// added: 496, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0)
///
/// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
/// added: 2048, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added:
/// 555, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size:
/// Some(64), added: 1549, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size:
/// Some(196), added: 1681, mode: MaxEncodedLen)
fn submit_parachain_heads_with_1kb_proof() -> Weight {
// Proof Size summary in bytes:
// Measured: `366`
// Estimated: `4648`
// Minimum execution time: 38_189 nanoseconds.
Weight::from_parts(39_252_000, 4648)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(3_u64))
}
/// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0)
///
/// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1),
/// added: 496, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0)
///
/// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
/// added: 2048, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added:
/// 555, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size:
/// Some(64), added: 1549, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size:
/// Some(196), added: 1681, mode: MaxEncodedLen)
fn submit_parachain_heads_with_16kb_proof() -> Weight {
// Proof Size summary in bytes:
// Measured: `366`
// Estimated: `4648`
// Minimum execution time: 62_868 nanoseconds.
Weight::from_parts(63_581_000, 4648)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(3_u64))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
/// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0)
///
/// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1),
/// added: 496, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0)
///
/// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
/// added: 2048, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added:
/// 555, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size:
/// Some(64), added: 1549, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size:
/// Some(196), added: 1681, mode: MaxEncodedLen)
///
/// The range of component `p` is `[1, 2]`.
fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight {
// Proof Size summary in bytes:
// Measured: `366`
// Estimated: `4648`
// Minimum execution time: 36_701 nanoseconds.
Weight::from_parts(38_597_828, 4648)
// Standard Error: 190_859
.saturating_add(Weight::from_parts(60_685, 0).saturating_mul(p.into()))
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().writes(3_u64))
}
/// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0)
///
/// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1),
/// added: 496, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0)
///
/// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
/// added: 2048, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added:
/// 555, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size:
/// Some(64), added: 1549, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size:
/// Some(196), added: 1681, mode: MaxEncodedLen)
fn submit_parachain_heads_with_1kb_proof() -> Weight {
// Proof Size summary in bytes:
// Measured: `366`
// Estimated: `4648`
// Minimum execution time: 38_189 nanoseconds.
Weight::from_parts(39_252_000, 4648)
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().writes(3_u64))
}
/// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0)
///
/// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1),
/// added: 496, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0)
///
/// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68),
/// added: 2048, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added:
/// 555, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size:
/// Some(64), added: 1549, mode: MaxEncodedLen)
///
/// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1)
///
/// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size:
/// Some(196), added: 1681, mode: MaxEncodedLen)
fn submit_parachain_heads_with_16kb_proof() -> Weight {
// Proof Size summary in bytes:
// Measured: `366`
// Estimated: `4648`
// Minimum execution time: 62_868 nanoseconds.
Weight::from_parts(63_581_000, 4648)
.saturating_add(RocksDbWeight::get().reads(4_u64))
.saturating_add(RocksDbWeight::get().writes(3_u64))
}
}
@@ -1,107 +0,0 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common 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.
// Parity Bridges Common 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 Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Weight-related utilities.
use crate::weights::{BridgeWeight, WeightInfo};
use bp_runtime::Size;
use frame_support::weights::{RuntimeDbWeight, Weight};
/// Size of the regular parachain head.
///
/// It's not that we are expecting all parachain heads to share the same size or that we would
/// reject all heads that have larger/lesser size. It is about head size that we use in benchmarks.
/// Relayer would need to pay additional fee for extra bytes.
///
/// 384 is a bit larger (1.3 times) than the size of the randomly chosen Polkadot block.
pub const DEFAULT_PARACHAIN_HEAD_SIZE: u32 = 384;
/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
/// some generic chain.
pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024;
/// Extended weight info.
pub trait WeightInfoExt: WeightInfo {
/// Storage proof overhead, that is included in every storage proof.
///
/// The relayer would pay some extra fee for additional proof bytes, since they mean
/// more hashing operations.
fn expected_extra_storage_proof_size() -> u32;
/// Weight of the parachain heads delivery extrinsic.
fn submit_parachain_heads_weight(
db_weight: RuntimeDbWeight,
proof: &impl Size,
parachains_count: u32,
) -> Weight {
// weight of the `submit_parachain_heads` with exactly `parachains_count` parachain
// heads of the default size (`DEFAULT_PARACHAIN_HEAD_SIZE`)
let base_weight = Self::submit_parachain_heads_with_n_parachains(parachains_count);
// overhead because of extra storage proof bytes
let expected_proof_size = parachains_count
.saturating_mul(DEFAULT_PARACHAIN_HEAD_SIZE)
.saturating_add(Self::expected_extra_storage_proof_size());
let actual_proof_size = proof.size();
let proof_size_overhead = Self::storage_proof_size_overhead(
actual_proof_size.saturating_sub(expected_proof_size),
);
// potential pruning weight (refunded if hasn't happened)
let pruning_weight =
Self::parachain_head_pruning_weight(db_weight).saturating_mul(parachains_count as u64);
base_weight.saturating_add(proof_size_overhead).saturating_add(pruning_weight)
}
/// Returns weight of single parachain head storage update.
///
/// This weight only includes db write operations that happens if parachain head is actually
/// updated. All extra weights (weight of storage proof validation, additional checks, ...) is
/// not included.
fn parachain_head_storage_write_weight(db_weight: RuntimeDbWeight) -> Weight {
// it's just a couple of operations - we need to write the hash (`ImportedParaHashes`) and
// the head itself (`ImportedParaHeads`. Pruning is not included here
db_weight.writes(2)
}
/// Returns weight of single parachain head pruning.
fn parachain_head_pruning_weight(db_weight: RuntimeDbWeight) -> Weight {
// it's just one write operation, we don't want any benchmarks for that
db_weight.writes(1)
}
/// Returns weight that needs to be accounted when storage proof of given size is received.
fn storage_proof_size_overhead(extra_proof_bytes: u32) -> Weight {
let extra_byte_weight = (Self::submit_parachain_heads_with_16kb_proof() -
Self::submit_parachain_heads_with_1kb_proof()) /
(15 * 1024);
extra_byte_weight.saturating_mul(extra_proof_bytes as u64)
}
}
impl WeightInfoExt for () {
fn expected_extra_storage_proof_size() -> u32 {
EXTRA_STORAGE_PROOF_SIZE
}
}
impl<T: frame_system::Config> WeightInfoExt for BridgeWeight<T> {
fn expected_extra_storage_proof_size() -> u32 {
EXTRA_STORAGE_PROOF_SIZE
}
}