mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 02:21:14 +00:00
Parachains pallet benchmarks (#1436)
* added parachains pallet benchmarks * deduplicate insertion of bridged header * pruning weight * fixes * fix compilation
This commit is contained in:
committed by
Bastian Köcher
parent
690a929cf6
commit
b870fe74f8
@@ -145,6 +145,7 @@ runtime-benchmarks = [
|
||||
"frame-system/runtime-benchmarks",
|
||||
"libsecp256k1",
|
||||
"pallet-bridge-messages/runtime-benchmarks",
|
||||
"pallet-bridge-parachains/runtime-benchmarks",
|
||||
"pallet-xcm/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
|
||||
@@ -515,9 +515,10 @@ parameter_types! {
|
||||
}
|
||||
|
||||
/// Instance of the with-Rialto parachains token swap pallet.
|
||||
pub type WitRialtoParachainsInstance = ();
|
||||
pub type WithRialtoParachainsInstance = ();
|
||||
|
||||
impl pallet_bridge_parachains::Config<WitRialtoParachainsInstance> for Runtime {
|
||||
impl pallet_bridge_parachains::Config<WithRialtoParachainsInstance> for Runtime {
|
||||
type WeightInfo = pallet_bridge_parachains::weights::MillauWeight<Runtime>;
|
||||
type BridgesGrandpaPalletInstance = RialtoGrandpaInstance;
|
||||
type ParasPalletName = RialtoParasPalletName;
|
||||
type TrackedParachains = frame_support::traits::Everything;
|
||||
@@ -807,7 +808,7 @@ impl_runtime_apis! {
|
||||
use bp_rialto_parachain::RIALTO_PARACHAIN_ID;
|
||||
let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::<
|
||||
Runtime,
|
||||
WitRialtoParachainsInstance,
|
||||
WithRialtoParachainsInstance,
|
||||
>::best_parachain_head(RIALTO_PARACHAIN_ID.into())
|
||||
.and_then(|encoded_header| bp_rialto_parachain::Header::decode(&mut &encoded_header.0[..]).ok());
|
||||
match best_rialto_parachain_head {
|
||||
@@ -901,11 +902,13 @@ impl_runtime_apis! {
|
||||
use frame_support::traits::StorageInfoTrait;
|
||||
|
||||
use pallet_bridge_messages::benchmarking::Pallet as MessagesBench;
|
||||
use pallet_bridge_parachains::benchmarking::Pallet as ParachainsBench;
|
||||
|
||||
let mut list = Vec::<BenchmarkList>::new();
|
||||
|
||||
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithRialtoMessagesInstance>);
|
||||
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa);
|
||||
list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::<Runtime, WithRialtoMessagesInstance>);
|
||||
|
||||
let storage_info = AllPalletsWithSystem::storage_info();
|
||||
|
||||
@@ -942,6 +945,10 @@ impl_runtime_apis! {
|
||||
MessageParams,
|
||||
MessageProofParams,
|
||||
};
|
||||
use pallet_bridge_parachains::benchmarking::{
|
||||
Pallet as ParachainsBench,
|
||||
Config as ParachainsConfig,
|
||||
};
|
||||
use rialto_messages::WithRialtoMessageBridge;
|
||||
|
||||
impl MessagesConfig<WithRialtoMessagesInstance> for Runtime {
|
||||
@@ -991,6 +998,19 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
impl ParachainsConfig<WithRialtoParachainsInstance> for Runtime {
|
||||
fn prepare_parachain_heads_proof(
|
||||
parachains: &[bp_polkadot_core::parachains::ParaId],
|
||||
parachain_head_size: u32,
|
||||
proof_size: bp_runtime::StorageProofSize,
|
||||
) -> (pallet_bridge_parachains::RelayBlockHash, bp_polkadot_core::parachains::ParaHeadsProof) {
|
||||
bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::<Runtime, WithRialtoParachainsInstance>(
|
||||
parachains,
|
||||
parachain_head_size,
|
||||
proof_size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
add_benchmark!(
|
||||
params,
|
||||
@@ -999,6 +1019,12 @@ impl_runtime_apis! {
|
||||
MessagesBench::<Runtime, WithRialtoMessagesInstance>
|
||||
);
|
||||
add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa);
|
||||
add_benchmark!(
|
||||
params,
|
||||
batches,
|
||||
pallet_bridge_parachains,
|
||||
ParachainsBench::<Runtime, WithRialtoParachainsInstance>
|
||||
);
|
||||
|
||||
Ok(batches)
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ impl TargetHeaderChain<ToRialtoParachainMessagePayload, bp_rialto_parachain::Acc
|
||||
WithRialtoParachainMessageBridge,
|
||||
bp_rialto_parachain::Header,
|
||||
Runtime,
|
||||
crate::WitRialtoParachainsInstance,
|
||||
crate::WithRialtoParachainsInstance,
|
||||
>(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof)
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,7 @@ impl SourceHeaderChain<bp_rialto_parachain::Balance> for RialtoParachain {
|
||||
WithRialtoParachainMessageBridge,
|
||||
bp_rialto_parachain::Header,
|
||||
Runtime,
|
||||
crate::WitRialtoParachainsInstance,
|
||||
crate::WithRialtoParachainsInstance,
|
||||
>(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof, messages_count)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ static_assertions = { version = "1.1", optional = true }
|
||||
# Bridge dependencies
|
||||
|
||||
bp-messages = { path = "../../primitives/messages", 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 = "../../modules/grandpa", default-features = false }
|
||||
@@ -49,6 +50,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-x
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-messages/std",
|
||||
"bp-parachains/std",
|
||||
"bp-polkadot-core/std",
|
||||
"bp-runtime/std",
|
||||
"codec/std",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
pub mod messages;
|
||||
pub mod messages_api;
|
||||
pub mod messages_benchmarking;
|
||||
pub mod parachains_benchmarking;
|
||||
|
||||
#[cfg(feature = "integrity-test")]
|
||||
pub mod integrity;
|
||||
|
||||
@@ -27,10 +27,11 @@ use crate::messages::{
|
||||
};
|
||||
|
||||
use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload};
|
||||
use bp_runtime::StorageProofSize;
|
||||
use codec::Encode;
|
||||
use frame_support::weights::{GetDispatchInfo, Weight};
|
||||
use pallet_bridge_messages::benchmarking::{
|
||||
MessageDeliveryProofParams, MessageParams, MessageProofParams, ProofSize,
|
||||
MessageDeliveryProofParams, MessageParams, MessageProofParams,
|
||||
};
|
||||
use sp_core::Hasher;
|
||||
use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero};
|
||||
@@ -59,7 +60,7 @@ where
|
||||
R: frame_system::Config<AccountId = AccountIdOf<ThisChain<B>>>
|
||||
+ pallet_balances::Config<BI, Balance = BalanceOf<ThisChain<B>>>
|
||||
+ pallet_bridge_grandpa::Config<FI>,
|
||||
R::BridgedChain: bp_runtime::Chain<Header = BH>,
|
||||
R::BridgedChain: bp_runtime::Chain<Hash = HashOf<BridgedChain<B>>, Header = BH>,
|
||||
B: MessageBridge,
|
||||
BI: 'static,
|
||||
FI: 'static,
|
||||
@@ -76,14 +77,14 @@ where
|
||||
+ IdentifyAccount<AccountId = AccountIdOf<ThisChain<B>>>,
|
||||
{
|
||||
let message_payload = match params.size {
|
||||
ProofSize::Minimal(ref size) => vec![0u8; *size as _],
|
||||
StorageProofSize::Minimal(ref size) => vec![0u8; *size as _],
|
||||
_ => vec![],
|
||||
};
|
||||
|
||||
// finally - prepare storage proof and update environment
|
||||
let (state_root, storage_proof) =
|
||||
prepare_messages_storage_proof::<B, BHH>(¶ms, message_payload);
|
||||
let bridged_header_hash = insert_bridged_chain_header::<R, FI, B, BH>(state_root);
|
||||
let bridged_header_hash = insert_header_to_grandpa_pallet::<R, FI>(state_root);
|
||||
|
||||
(
|
||||
FromBridgedChainMessagesProof {
|
||||
@@ -103,7 +104,7 @@ pub fn prepare_message_delivery_proof<R, FI, B, BH, BHH>(
|
||||
) -> FromBridgedChainMessagesDeliveryProof<HashOf<BridgedChain<B>>>
|
||||
where
|
||||
R: pallet_bridge_grandpa::Config<FI>,
|
||||
R::BridgedChain: bp_runtime::Chain<Header = BH>,
|
||||
R::BridgedChain: bp_runtime::Chain<Hash = HashOf<BridgedChain<B>>, Header = BH>,
|
||||
FI: 'static,
|
||||
B: MessageBridge,
|
||||
BH: Header<Hash = HashOf<BridgedChain<B>>>,
|
||||
@@ -131,7 +132,7 @@ where
|
||||
let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
||||
|
||||
// finally insert header with given state root to our storage
|
||||
let bridged_header_hash = insert_bridged_chain_header::<R, FI, B, BH>(root);
|
||||
let bridged_header_hash = insert_header_to_grandpa_pallet::<R, FI>(root);
|
||||
|
||||
FromBridgedChainMessagesDeliveryProof {
|
||||
bridged_header_hash: bridged_header_hash.into(),
|
||||
@@ -203,19 +204,16 @@ where
|
||||
(root, storage_proof)
|
||||
}
|
||||
|
||||
/// Insert Bridged chain header with given state root into storage of GRANDPA pallet at This chain.
|
||||
fn insert_bridged_chain_header<R, FI, B, BH>(
|
||||
state_root: HashOf<BridgedChain<B>>,
|
||||
) -> HashOf<BridgedChain<B>>
|
||||
/// Insert header to the bridge GRANDPA pallet.
|
||||
pub(crate) fn insert_header_to_grandpa_pallet<R, GI>(
|
||||
state_root: bp_runtime::HashOf<R::BridgedChain>,
|
||||
) -> bp_runtime::HashOf<R::BridgedChain>
|
||||
where
|
||||
R: pallet_bridge_grandpa::Config<FI>,
|
||||
R::BridgedChain: bp_runtime::Chain<Header = BH>,
|
||||
FI: 'static,
|
||||
B: MessageBridge,
|
||||
BH: Header<Hash = HashOf<BridgedChain<B>>>,
|
||||
HashOf<BridgedChain<B>>: Default,
|
||||
R: pallet_bridge_grandpa::Config<GI>,
|
||||
GI: 'static,
|
||||
R::BridgedChain: bp_runtime::Chain,
|
||||
{
|
||||
let bridged_header = BH::new(
|
||||
let bridged_header = bp_runtime::HeaderOf::<R::BridgedChain>::new(
|
||||
Zero::zero(),
|
||||
Default::default(),
|
||||
state_root,
|
||||
@@ -223,16 +221,20 @@ where
|
||||
Default::default(),
|
||||
);
|
||||
let bridged_header_hash = bridged_header.hash();
|
||||
pallet_bridge_grandpa::initialize_for_benchmarks::<R, FI>(bridged_header);
|
||||
pallet_bridge_grandpa::initialize_for_benchmarks::<R, GI>(bridged_header);
|
||||
bridged_header_hash
|
||||
}
|
||||
|
||||
/// Populate trie with dummy keys+values until trie has at least given size.
|
||||
fn grow_trie<H: Hasher>(mut root: H::Out, mdb: &mut MemoryDB<H>, trie_size: ProofSize) -> H::Out {
|
||||
pub fn grow_trie<H: Hasher>(
|
||||
mut root: H::Out,
|
||||
mdb: &mut MemoryDB<H>,
|
||||
trie_size: StorageProofSize,
|
||||
) -> H::Out {
|
||||
let (iterations, leaf_size, minimal_trie_size) = match trie_size {
|
||||
ProofSize::Minimal(_) => return root,
|
||||
ProofSize::HasLargeLeaf(size) => (1, size, size),
|
||||
ProofSize::HasExtraNodes(size) => (8, 1, size),
|
||||
StorageProofSize::Minimal(_) => return root,
|
||||
StorageProofSize::HasLargeLeaf(size) => (1, size, size),
|
||||
StorageProofSize::HasExtraNodes(size) => (8, 1, size),
|
||||
};
|
||||
|
||||
let mut key_index = 0;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Everything required to run benchmarks of parachains finality module.
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use crate::messages_benchmarking::{grow_trie, insert_header_to_grandpa_pallet};
|
||||
|
||||
use bp_parachains::parachain_head_storage_key_at_source;
|
||||
use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId};
|
||||
use bp_runtime::StorageProofSize;
|
||||
use codec::Encode;
|
||||
use frame_support::traits::Get;
|
||||
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher};
|
||||
use sp_std::prelude::*;
|
||||
use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut};
|
||||
|
||||
/// Prepare proof of messages for the `receive_messages_proof` call.
|
||||
///
|
||||
/// In addition to returning valid messages proof, environment is prepared to verify this message
|
||||
/// proof.
|
||||
pub fn prepare_parachain_heads_proof<R, PI>(
|
||||
parachains: &[ParaId],
|
||||
parachain_head_size: u32,
|
||||
size: StorageProofSize,
|
||||
) -> (RelayBlockHash, ParaHeadsProof)
|
||||
where
|
||||
R: pallet_bridge_parachains::Config<PI>
|
||||
+ pallet_bridge_grandpa::Config<R::BridgesGrandpaPalletInstance>,
|
||||
PI: 'static,
|
||||
<R as pallet_bridge_grandpa::Config<R::BridgesGrandpaPalletInstance>>::BridgedChain:
|
||||
bp_runtime::Chain<Hash = RelayBlockHash>,
|
||||
{
|
||||
let parachain_head = ParaHead(vec![0u8; parachain_head_size as usize]);
|
||||
|
||||
// insert all heads to the trie
|
||||
let mut storage_keys = Vec::with_capacity(parachains.len());
|
||||
let mut state_root = Default::default();
|
||||
let mut mdb = MemoryDB::default();
|
||||
{
|
||||
let mut trie = TrieDBMutV1::<RelayBlockHasher>::new(&mut mdb, &mut state_root);
|
||||
|
||||
// insert parachain heads
|
||||
for parachain in parachains {
|
||||
let storage_key =
|
||||
parachain_head_storage_key_at_source(R::ParasPalletName::get(), *parachain);
|
||||
trie.insert(&storage_key.0, ¶chain_head.encode())
|
||||
.map_err(|_| "TrieMut::insert has failed")
|
||||
.expect("TrieMut::insert should not fail in benchmarks");
|
||||
storage_keys.push(storage_key);
|
||||
}
|
||||
}
|
||||
state_root = grow_trie(state_root, &mut mdb, size);
|
||||
|
||||
// generate heads storage proof
|
||||
let mut proof_recorder = Recorder::<RelayBlockHash>::new();
|
||||
record_all_keys::<LayoutV1<RelayBlockHasher>, _>(&mdb, &state_root, &mut proof_recorder)
|
||||
.map_err(|_| "record_all_keys has failed")
|
||||
.expect("record_all_keys should not fail in benchmarks");
|
||||
let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
||||
|
||||
let relay_block_hash =
|
||||
insert_header_to_grandpa_pallet::<R, R::BridgesGrandpaPalletInstance>(state_root);
|
||||
|
||||
(relay_block_hash, ParaHeadsProof(proof))
|
||||
}
|
||||
@@ -26,7 +26,7 @@ use bp_messages::{
|
||||
InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer,
|
||||
UnrewardedRelayersState,
|
||||
};
|
||||
use bp_runtime::messages::DispatchFeePayment;
|
||||
use bp_runtime::{messages::DispatchFeePayment, StorageProofSize};
|
||||
use frame_benchmarking::{account, benchmarks_instance_pallet};
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use frame_system::RawOrigin;
|
||||
@@ -37,20 +37,6 @@ const SEED: u32 = 0;
|
||||
/// Pallet we're benchmarking here.
|
||||
pub struct Pallet<T: Config<I>, I: 'static>(crate::Pallet<T, I>);
|
||||
|
||||
/// Proof size requirements.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ProofSize {
|
||||
/// The proof is expected to be minimal. If value size may be changed, then it is expected to
|
||||
/// have given size.
|
||||
Minimal(u32),
|
||||
/// The proof is expected to have at least given size and grow by increasing number of trie
|
||||
/// nodes included in the proof.
|
||||
HasExtraNodes(u32),
|
||||
/// The proof is expected to have at least given size and grow by increasing value that is
|
||||
/// stored in the trie.
|
||||
HasLargeLeaf(u32),
|
||||
}
|
||||
|
||||
/// Benchmark-specific message parameters.
|
||||
#[derive(Debug)]
|
||||
pub struct MessageParams<ThisAccountId> {
|
||||
@@ -70,7 +56,7 @@ pub struct MessageProofParams {
|
||||
/// If `Some`, the proof needs to include this outbound lane data.
|
||||
pub outbound_lane_data: Option<OutboundLaneData>,
|
||||
/// Proof size requirements.
|
||||
pub size: ProofSize,
|
||||
pub size: StorageProofSize,
|
||||
/// Where the fee for dispatching message is paid?
|
||||
pub dispatch_fee_payment: DispatchFeePayment,
|
||||
}
|
||||
@@ -83,7 +69,7 @@ pub struct MessageDeliveryProofParams<ThisChainAccountId> {
|
||||
/// The proof needs to include this inbound lane data.
|
||||
pub inbound_lane_data: InboundLaneData<ThisChainAccountId>,
|
||||
/// Proof size requirements.
|
||||
pub size: ProofSize,
|
||||
pub size: StorageProofSize,
|
||||
}
|
||||
|
||||
/// Trait that must be implemented by runtime.
|
||||
@@ -302,7 +288,7 @@ benchmarks_instance_pallet! {
|
||||
lane: T::bench_lane_id(),
|
||||
message_nonces: 21..=21,
|
||||
outbound_lane_data: None,
|
||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||
});
|
||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||
@@ -337,7 +323,7 @@ benchmarks_instance_pallet! {
|
||||
lane: T::bench_lane_id(),
|
||||
message_nonces: 21..=22,
|
||||
outbound_lane_data: None,
|
||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||
});
|
||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight)
|
||||
@@ -376,7 +362,7 @@ benchmarks_instance_pallet! {
|
||||
latest_received_nonce: 20,
|
||||
latest_generated_nonce: 21,
|
||||
}),
|
||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||
});
|
||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||
@@ -408,7 +394,7 @@ benchmarks_instance_pallet! {
|
||||
lane: T::bench_lane_id(),
|
||||
message_nonces: 21..=21,
|
||||
outbound_lane_data: None,
|
||||
size: ProofSize::HasExtraNodes(1024),
|
||||
size: StorageProofSize::HasExtraNodes(1024),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||
});
|
||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||
@@ -443,7 +429,7 @@ benchmarks_instance_pallet! {
|
||||
lane: T::bench_lane_id(),
|
||||
message_nonces: 21..=21,
|
||||
outbound_lane_data: None,
|
||||
size: ProofSize::HasExtraNodes(16 * 1024),
|
||||
size: StorageProofSize::HasExtraNodes(16 * 1024),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
|
||||
});
|
||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||
@@ -477,7 +463,7 @@ benchmarks_instance_pallet! {
|
||||
lane: T::bench_lane_id(),
|
||||
message_nonces: 21..=21,
|
||||
outbound_lane_data: None,
|
||||
size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH),
|
||||
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||
});
|
||||
}: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight)
|
||||
@@ -517,7 +503,7 @@ benchmarks_instance_pallet! {
|
||||
}].into_iter().collect(),
|
||||
last_confirmed_nonce: 0,
|
||||
},
|
||||
size: ProofSize::Minimal(0),
|
||||
size: StorageProofSize::Minimal(0),
|
||||
});
|
||||
}: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state)
|
||||
verify {
|
||||
@@ -560,7 +546,7 @@ benchmarks_instance_pallet! {
|
||||
}].into_iter().collect(),
|
||||
last_confirmed_nonce: 0,
|
||||
},
|
||||
size: ProofSize::Minimal(0),
|
||||
size: StorageProofSize::Minimal(0),
|
||||
});
|
||||
}: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state)
|
||||
verify {
|
||||
@@ -606,7 +592,7 @@ benchmarks_instance_pallet! {
|
||||
].into_iter().collect(),
|
||||
last_confirmed_nonce: 0,
|
||||
},
|
||||
size: ProofSize::Minimal(0),
|
||||
size: StorageProofSize::Minimal(0),
|
||||
});
|
||||
}: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state)
|
||||
verify {
|
||||
|
||||
@@ -20,6 +20,7 @@ pallet-bridge-grandpa = { path = "../grandpa", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -50,3 +51,6 @@ std = [
|
||||
"sp-std/std",
|
||||
"sp-trie/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2019-2021 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::{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> {
|
||||
/// 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,
|
||||
) -> (RelayBlockHash, ParaHeadsProof);
|
||||
}
|
||||
|
||||
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..1024;
|
||||
|
||||
let sender = account("sender", 0, 0);
|
||||
let parachains = (1..=p).map(ParaId).collect::<Vec<_>>();
|
||||
let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
||||
¶chains,
|
||||
DEFAULT_PARACHAIN_HEAD_SIZE,
|
||||
StorageProofSize::Minimal(0),
|
||||
);
|
||||
}: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), 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![ParaId(1)];
|
||||
let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
||||
¶chains,
|
||||
DEFAULT_PARACHAIN_HEAD_SIZE,
|
||||
StorageProofSize::HasExtraNodes(1024),
|
||||
);
|
||||
|
||||
}: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), 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![ParaId(1)];
|
||||
let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof(
|
||||
¶chains,
|
||||
DEFAULT_PARACHAIN_HEAD_SIZE,
|
||||
StorageProofSize::HasExtraNodes(16 * 1024),
|
||||
);
|
||||
|
||||
}: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof)
|
||||
verify {
|
||||
for parachain in parachains {
|
||||
assert!(crate::Pallet::<T, I>::best_parachain_head(parachain).is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,11 +23,14 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub use weights::WeightInfo;
|
||||
pub use weights_ext::WeightInfoExt;
|
||||
|
||||
use bp_parachains::parachain_head_storage_key_at_source;
|
||||
use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId};
|
||||
use bp_runtime::StorageProofError;
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{traits::Contains, RuntimeDebug};
|
||||
use frame_support::{traits::Contains, weights::PostDispatchInfo, RuntimeDebug};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
use sp_std::vec::Vec;
|
||||
@@ -35,6 +38,12 @@ use sp_std::vec::Vec;
|
||||
// Re-export in crate namespace for `construct_runtime!`.
|
||||
pub use pallet::*;
|
||||
|
||||
pub mod weights;
|
||||
pub mod weights_ext;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub mod benchmarking;
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
|
||||
@@ -56,12 +65,23 @@ pub struct BestParaHead {
|
||||
pub next_imported_hash_position: u32,
|
||||
}
|
||||
|
||||
/// Artifacts of the parachains head update.
|
||||
struct UpdateParachainHeadArtifacts {
|
||||
/// New best head of the parachain.
|
||||
pub best_head: BestParaHead,
|
||||
/// If `true`, some old parachain head has been pruned during update.
|
||||
pub prune_happened: bool,
|
||||
}
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
/// Weight info of the given parachains pallet.
|
||||
pub type WeightInfoOf<T, I> = <T as Config<I>>::WeightInfo;
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T, I = ()> {
|
||||
/// Relay chain block is unknown to us.
|
||||
@@ -81,6 +101,9 @@ pub mod pallet {
|
||||
pub trait Config<I: 'static = ()>:
|
||||
pallet_bridge_grandpa::Config<Self::BridgesGrandpaPalletInstance>
|
||||
{
|
||||
/// Benchmarks results from runtime we're plugged into.
|
||||
type WeightInfo: WeightInfoExt;
|
||||
|
||||
/// Instance of bridges GRANDPA pallet (within this runtime) that this pallet is linked to.
|
||||
///
|
||||
/// The GRANDPA pallet instance must be configured to import headers of relay chain that
|
||||
@@ -145,13 +168,17 @@ pub mod pallet {
|
||||
/// `polkadot-runtime-parachains::paras` pallet instance, deployed at the bridged chain.
|
||||
/// The proof is supposed to be crafted at the `relay_header_hash` that must already be
|
||||
/// imported by corresponding GRANDPA pallet at this chain.
|
||||
#[pallet::weight(0)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1391
|
||||
#[pallet::weight(WeightInfoOf::<T, I>::submit_parachain_heads_weight(
|
||||
T::DbWeight::get(),
|
||||
parachain_heads_proof,
|
||||
parachains.len() as _,
|
||||
))]
|
||||
pub fn submit_parachain_heads(
|
||||
_origin: OriginFor<T>,
|
||||
relay_block_hash: RelayBlockHash,
|
||||
parachains: Vec<ParaId>,
|
||||
parachain_heads_proof: ParaHeadsProof,
|
||||
) -> DispatchResult {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
// we'll need relay chain header to verify that parachains heads are always increasing.
|
||||
let relay_block = pallet_bridge_grandpa::ImportedHeaders::<
|
||||
T,
|
||||
@@ -161,9 +188,14 @@ pub mod pallet {
|
||||
let relay_block_number = *relay_block.number();
|
||||
|
||||
// now parse storage proof and read parachain heads
|
||||
let mut actual_weight = WeightInfoOf::<T, I>::submit_parachain_heads_weight(
|
||||
T::DbWeight::get(),
|
||||
¶chain_heads_proof,
|
||||
parachains.len() as _,
|
||||
);
|
||||
pallet_bridge_grandpa::Pallet::<T, T::BridgesGrandpaPalletInstance>::parse_finalized_storage_proof(
|
||||
relay_block_hash,
|
||||
sp_trie::StorageProof::new(parachain_heads_proof),
|
||||
sp_trie::StorageProof::new(parachain_heads_proof.0),
|
||||
move |storage| {
|
||||
for parachain in parachains {
|
||||
// if we're not tracking this parachain, we'll just ignore its head proof here
|
||||
@@ -202,21 +234,27 @@ pub mod pallet {
|
||||
},
|
||||
};
|
||||
|
||||
let _: Result<_, ()> = BestParaHeads::<T, I>::try_mutate(parachain, |stored_best_head| {
|
||||
*stored_best_head = Some(Pallet::<T, I>::update_parachain_head(
|
||||
let prune_happened: Result<_, ()> = BestParaHeads::<T, I>::try_mutate(parachain, |stored_best_head| {
|
||||
let artifacts = Pallet::<T, I>::update_parachain_head(
|
||||
parachain,
|
||||
stored_best_head.take(),
|
||||
relay_block_number,
|
||||
parachain_head,
|
||||
)?);
|
||||
Ok(())
|
||||
)?;
|
||||
*stored_best_head = Some(artifacts.best_head);
|
||||
Ok(artifacts.prune_happened)
|
||||
});
|
||||
|
||||
if matches!(prune_happened, Err(_) | Ok(false)) {
|
||||
actual_weight = actual_weight
|
||||
.saturating_sub(WeightInfoOf::<T, I>::parachain_head_pruning_weight(T::DbWeight::get()));
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.map_err(|_| Error::<T, I>::InvalidStorageProof)?;
|
||||
|
||||
Ok(())
|
||||
Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +307,7 @@ pub mod pallet {
|
||||
stored_best_head: Option<BestParaHead>,
|
||||
updated_at_relay_block_number: RelayBlockNumber,
|
||||
updated_head: ParaHead,
|
||||
) -> Result<BestParaHead, ()> {
|
||||
) -> Result<UpdateParachainHeadArtifacts, ()> {
|
||||
// check if head has been already updated at better relay chain block. Without this
|
||||
// check, we may import heads in random order
|
||||
let updated_head_hash = updated_head.hash();
|
||||
@@ -332,6 +370,7 @@ pub mod pallet {
|
||||
);
|
||||
|
||||
// remove old head
|
||||
let prune_happened = head_hash_to_prune.is_ok();
|
||||
if let Ok(head_hash_to_prune) = head_hash_to_prune {
|
||||
log::trace!(
|
||||
target: "runtime::bridge-parachains",
|
||||
@@ -342,7 +381,7 @@ pub mod pallet {
|
||||
ImportedParaHeads::<T, I>::remove(parachain, head_hash_to_prune);
|
||||
}
|
||||
|
||||
Ok(updated_best_para_head)
|
||||
Ok(UpdateParachainHeadArtifacts { best_head: updated_best_para_head, prune_happened })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -355,7 +394,12 @@ mod tests {
|
||||
};
|
||||
|
||||
use bp_test_utils::{authority_list, make_default_justification};
|
||||
use frame_support::{assert_noop, assert_ok, traits::OnInitialize};
|
||||
use frame_support::{
|
||||
assert_noop, assert_ok,
|
||||
dispatch::DispatchResultWithPostInfo,
|
||||
traits::{Get, OnInitialize},
|
||||
weights::Weight,
|
||||
};
|
||||
use sp_trie::{
|
||||
record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut,
|
||||
};
|
||||
@@ -414,7 +458,7 @@ mod tests {
|
||||
.expect("record_all_keys should not fail in benchmarks");
|
||||
let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect();
|
||||
|
||||
(root, storage_proof)
|
||||
(root, ParaHeadsProof(storage_proof))
|
||||
}
|
||||
|
||||
fn initial_best_head(parachain: u32) -> BestParaHead {
|
||||
@@ -437,7 +481,7 @@ mod tests {
|
||||
relay_chain_block: RelayBlockNumber,
|
||||
relay_state_root: RelayBlockHash,
|
||||
proof: ParaHeadsProof,
|
||||
) -> sp_runtime::DispatchResult {
|
||||
) -> DispatchResultWithPostInfo {
|
||||
Pallet::<TestRuntime>::submit_parachain_heads(
|
||||
Origin::signed(1),
|
||||
test_relay_header(relay_chain_block, relay_state_root).hash(),
|
||||
@@ -446,6 +490,16 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
fn weight_of_import_parachain_1_head(proof: &ParaHeadsProof, prune_expected: bool) -> Weight {
|
||||
let db_weight = <TestRuntime as frame_system::Config>::DbWeight::get();
|
||||
WeightInfoOf::<TestRuntime, ()>::submit_parachain_heads_weight(db_weight, proof, 1)
|
||||
.saturating_sub(if prune_expected {
|
||||
0
|
||||
} else {
|
||||
WeightInfoOf::<TestRuntime, ()>::parachain_head_pruning_weight(db_weight)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imports_initial_parachain_heads() {
|
||||
let (state_root, proof) =
|
||||
@@ -636,7 +690,11 @@ mod tests {
|
||||
} else {
|
||||
proceed(i, state_root);
|
||||
}
|
||||
assert_ok!(import_parachain_1_head(i, state_root, proof));
|
||||
|
||||
let expected_weight = weight_of_import_parachain_1_head(&proof, false);
|
||||
let result = import_parachain_1_head(i, state_root, proof);
|
||||
assert_ok!(result);
|
||||
assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight));
|
||||
}
|
||||
|
||||
// nothing is pruned yet
|
||||
@@ -649,7 +707,10 @@ mod tests {
|
||||
let (state_root, proof) =
|
||||
prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]);
|
||||
proceed(heads_to_keep, state_root);
|
||||
assert_ok!(import_parachain_1_head(heads_to_keep, state_root, proof));
|
||||
let expected_weight = weight_of_import_parachain_1_head(&proof, true);
|
||||
let result = import_parachain_1_head(heads_to_keep, state_root, proof);
|
||||
assert_ok!(result);
|
||||
assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight));
|
||||
|
||||
// and the head#0 is pruned
|
||||
assert!(
|
||||
|
||||
@@ -112,6 +112,7 @@ parameter_types! {
|
||||
}
|
||||
|
||||
impl pallet_bridge_parachains::Config for TestRuntime {
|
||||
type WeightInfo = ();
|
||||
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
|
||||
type ParasPalletName = ParasPalletName;
|
||||
type TrackedParachains = IsInVec<GetTenFirstParachains>;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright 2019-2021 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: 2022-06-06, STEPS: 50, REPEAT: 20
|
||||
//! LOW RANGE: [], HIGH RANGE: []
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
|
||||
//! CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// target/release/millau-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/millau-weight-template.hbs
|
||||
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
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` using the Millau node and recommended hardware.
|
||||
pub struct MillauWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for MillauWeight<T> {
|
||||
fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((18_729_000 as Weight).saturating_mul(p as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(p as Weight)))
|
||||
.saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(p as Weight)))
|
||||
}
|
||||
fn submit_parachain_heads_with_1kb_proof() -> Weight {
|
||||
(25_355_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn submit_parachain_heads_with_16kb_proof() -> Weight {
|
||||
(74_570_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight {
|
||||
(0 as Weight)
|
||||
.saturating_add((18_729_000 as Weight).saturating_mul(p as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(p as Weight)))
|
||||
.saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(p as Weight)))
|
||||
}
|
||||
fn submit_parachain_heads_with_1kb_proof() -> Weight {
|
||||
(25_355_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
fn submit_parachain_heads_with_16kb_proof() -> Weight {
|
||||
(74_570_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2019-2021 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::{MillauWeight, 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
|
||||
/// the Rialto 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_hint();
|
||||
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 = (parachains_count as Weight)
|
||||
.saturating_mul(Self::parachain_head_pruning_weight(db_weight));
|
||||
|
||||
base_weight.saturating_add(proof_size_overhead).saturating_add(pruning_weight)
|
||||
}
|
||||
|
||||
/// 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_proof_bytes_in_bytes = extra_proof_bytes as Weight;
|
||||
let extra_byte_weight = (Self::submit_parachain_heads_with_16kb_proof() -
|
||||
Self::submit_parachain_heads_with_1kb_proof()) /
|
||||
(15 * 1024);
|
||||
extra_proof_bytes_in_bytes.saturating_mul(extra_byte_weight)
|
||||
}
|
||||
}
|
||||
|
||||
impl WeightInfoExt for () {
|
||||
fn expected_extra_storage_proof_size() -> u32 {
|
||||
EXTRA_STORAGE_PROOF_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: frame_system::Config> WeightInfoExt for MillauWeight<T> {
|
||||
fn expected_extra_storage_proof_size() -> u32 {
|
||||
EXTRA_STORAGE_PROOF_SIZE
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
//! chains. Having pallets that are referencing polkadot, would mean that there may
|
||||
//! be two versions of polkadot crates included in the runtime. Which is bad.
|
||||
|
||||
use bp_runtime::Size;
|
||||
use frame_support::RuntimeDebug;
|
||||
use parity_scale_codec::{CompactAs, Decode, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
@@ -88,4 +89,12 @@ pub type ParaHash = crate::Hash;
|
||||
pub type ParaHasher = crate::Hasher;
|
||||
|
||||
/// Raw storage proof of parachain heads, stored in polkadot-like chain runtime.
|
||||
pub type ParaHeadsProof = Vec<Vec<u8>>;
|
||||
#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
|
||||
pub struct ParaHeadsProof(pub Vec<Vec<u8>>);
|
||||
|
||||
impl Size for ParaHeadsProof {
|
||||
fn size_hint(&self) -> u32 {
|
||||
u32::try_from(self.0.iter().fold(0usize, |sum, node| sum.saturating_add(node.len())))
|
||||
.unwrap_or(u32::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ pub use chain::{
|
||||
HasherOf, HeaderOf, IndexOf, SignatureOf, TransactionEraOf,
|
||||
};
|
||||
pub use frame_support::storage::storage_prefix as storage_value_final_key;
|
||||
pub use storage_proof::{Error as StorageProofError, StorageProofChecker};
|
||||
pub use storage_proof::{
|
||||
Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker,
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use storage_proof::craft_valid_storage_proof;
|
||||
|
||||
@@ -22,6 +22,22 @@ use sp_runtime::RuntimeDebug;
|
||||
use sp_std::vec::Vec;
|
||||
use sp_trie::{read_trie_value, LayoutV1, MemoryDB, StorageProof};
|
||||
|
||||
/// Storage proof size requirements.
|
||||
///
|
||||
/// This is currently used by benchmarks when generating storage proofs.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ProofSize {
|
||||
/// The proof is expected to be minimal. If value size may be changed, then it is expected to
|
||||
/// have given size.
|
||||
Minimal(u32),
|
||||
/// The proof is expected to have at least given size and grow by increasing number of trie
|
||||
/// nodes included in the proof.
|
||||
HasExtraNodes(u32),
|
||||
/// The proof is expected to have at least given size and grow by increasing value that is
|
||||
/// stored in the trie.
|
||||
HasLargeLeaf(u32),
|
||||
}
|
||||
|
||||
/// This struct is used to read storage values from a subset of a Merklized database. The "proof"
|
||||
/// is a subset of the nodes in the Merkle structure of the database, so that it provides
|
||||
/// authentication against a known Merkle root as well as the values in the database themselves.
|
||||
|
||||
@@ -49,5 +49,5 @@ pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder =
|
||||
DirectSubmitParachainHeadsCallBuilder<
|
||||
RialtoParachainsToMillau,
|
||||
millau_runtime::Runtime,
|
||||
millau_runtime::WitRialtoParachainsInstance,
|
||||
millau_runtime::WithRialtoParachainsInstance,
|
||||
>;
|
||||
|
||||
@@ -161,6 +161,6 @@ where
|
||||
.iter_nodes()
|
||||
.collect();
|
||||
|
||||
Ok(parachain_heads_proof)
|
||||
Ok(ParaHeadsProof(parachain_heads_proof))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +664,7 @@ mod tests {
|
||||
.ok_or(TestError::MissingParachainHeadProof)?,
|
||||
);
|
||||
}
|
||||
Ok(proofs)
|
||||
Ok(ParaHeadsProof(proofs))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user