From 00195629095a2639f47327a46ca7ad81a8a07c92 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 Jan 2023 15:55:42 +0300 Subject: [PATCH] Functions to benchmark messages pallet with linked to parachain (#1817) * functions to benchmark messages pallet with linked to parachain * unused imports * fmt --- bin/millau/runtime/src/lib.rs | 6 +- bin/runtime-common/Cargo.toml | 1 + .../src/messages_benchmarking.rs | 201 ++++++++++++++---- modules/parachains/src/lib.rs | 26 +++ 4 files changed, 186 insertions(+), 48 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 5aba458216d..b0dc28cf27e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -983,7 +983,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof, prepare_message_proof}; + use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_grandpa_chain, prepare_message_proof_from_grandpa_chain}; use pallet_bridge_messages::benchmarking::{ Pallet as MessagesBench, Config as MessagesConfig, @@ -1004,7 +1004,7 @@ impl_runtime_apis! { fn prepare_message_proof( params: MessageProofParams, ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { - prepare_message_proof::( + prepare_message_proof_from_grandpa_chain::( params, ) } @@ -1012,7 +1012,7 @@ impl_runtime_apis! { fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> rialto_messages::ToRialtoMessagesDeliveryProof { - prepare_message_delivery_proof::( + prepare_message_delivery_proof_from_grandpa_chain::( params, ) } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 9e8e6b29db2..7d538671646 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -82,6 +82,7 @@ std = [ runtime-benchmarks = [ "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] integrity-test = [ diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index afe95422d18..e7ca26d952e 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -22,7 +22,7 @@ use crate::{ messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, ThisChain, + AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof, ThisChain, }, messages_generation::{ encode_all_messages, encode_lane_data, grow_trie, prepare_messages_storage_proof, @@ -30,52 +30,46 @@ use crate::{ }; use bp_messages::storage_keys; -use bp_runtime::{record_all_trie_keys, StorageProofSize}; +use bp_polkadot_core::parachains::ParaHash; +use bp_runtime::{record_all_trie_keys, Chain, Parachain, StorageProofSize, UnderlyingChainOf}; use codec::Encode; -use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; +use frame_support::weights::Weight; use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; -use sp_core::Hasher; -use sp_runtime::traits::{Header, MaybeSerializeDeserialize, Zero}; -use sp_std::{fmt::Debug, prelude::*}; +use sp_runtime::traits::{Header, Zero}; +use sp_std::prelude::*; use sp_trie::{trie_types::TrieDBMutBuilderV1, 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_message_proof( +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses GRANDPA finality. For parachains, please use the `prepare_message_proof_from_parachain` +/// function. +pub fn prepare_message_proof_from_grandpa_chain( params: MessageProofParams, ) -> (FromBridgedChainMessagesProof>>, Weight) where - R: frame_system::Config>> - + pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain>, Header = BH>, - B: MessageBridge, - BI: 'static, + R: pallet_bridge_grandpa::Config>>, FI: 'static, - BH: Header>>, - BHH: Hasher>>, - AccountIdOf>: PartialEq + sp_std::fmt::Debug, - AccountIdOf>: From<[u8; 32]>, - BalanceOf>: Debug + MaybeSerializeDeserialize, - CallOf>: From> + GetDispatchInfo, - HashOf>: Copy + Default, + B: MessageBridge, { - let message_payload = match params.size { - StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }; - - // finally - prepare storage proof and update environment + // prepare storage proof let (state_root, storage_proof) = prepare_messages_storage_proof::( params.lane, params.message_nonces.clone(), params.outbound_lane_data, params.size, - message_payload, + match params.size { + StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }, encode_all_messages, encode_lane_data, ); + + // update runtime storage let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); ( @@ -90,18 +84,115 @@ where ) } +/// 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. +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses parachain finality. For GRANDPA chains, please use the +/// `prepare_message_proof_from_grandpa_chain` function. +pub fn prepare_message_proof_from_parachain( + params: MessageProofParams, +) -> (FromBridgedChainMessagesProof>>, Weight) +where + R: pallet_bridge_parachains::Config, + PI: 'static, + B: MessageBridge, + UnderlyingChainOf>: Chain + Parachain, +{ + // prepare storage proof + let (state_root, storage_proof) = prepare_messages_storage_proof::( + params.lane, + params.message_nonces.clone(), + params.outbound_lane_data, + params.size, + match params.size { + StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }, + encode_all_messages, + encode_lane_data, + ); + + // update runtime storage + let (_, bridged_header_hash) = + insert_header_to_parachains_pallet::>>(state_root); + + ( + FromBridgedChainMessagesProof { + bridged_header_hash, + storage_proof, + lane: params.lane, + nonces_start: *params.message_nonces.start(), + nonces_end: *params.message_nonces.end(), + }, + Weight::zero(), + ) +} + /// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. -pub fn prepare_message_delivery_proof( +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses GRANDPA finality. For parachains, please use the +/// `prepare_message_delivery_proof_from_parachain` function. +pub fn prepare_message_delivery_proof_from_grandpa_chain( params: MessageDeliveryProofParams>>, ) -> FromBridgedChainMessagesDeliveryProof>> where - R: pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain>, Header = BH>, + R: pallet_bridge_grandpa::Config>>, FI: 'static, B: MessageBridge, - BH: Header>>, - BHH: Hasher>>, - HashOf>: Copy + Default, +{ + // prepare storage proof + let lane = params.lane; + let (state_root, storage_proof) = prepare_message_delivery_proof::(params); + + // update runtime storage + let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); + + FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: bridged_header_hash.into(), + storage_proof, + lane, + } +} + +/// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses parachain finality. For GRANDPA chains, please use the +/// `prepare_message_delivery_proof_from_grandpa_chain` function. +pub fn prepare_message_delivery_proof_from_parachain( + params: MessageDeliveryProofParams>>, +) -> FromBridgedChainMessagesDeliveryProof>> +where + R: pallet_bridge_parachains::Config, + PI: 'static, + B: MessageBridge, + UnderlyingChainOf>: Chain + Parachain, +{ + // prepare storage proof + let lane = params.lane; + let (state_root, storage_proof) = prepare_message_delivery_proof::(params); + + // update runtime storage + let (_, bridged_header_hash) = + insert_header_to_parachains_pallet::>>(state_root); + + FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: bridged_header_hash.into(), + storage_proof, + lane, + } +} + +/// Prepare in-memory message delivery proof, without inserting anything to the runtime storage. +fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams>>, +) -> (HashOf>, RawStorageProof) +where + B: MessageBridge, { // prepare Bridged chain storage with inbound lane state let storage_key = @@ -109,7 +200,8 @@ where let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); + let mut trie = + TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); @@ -117,20 +209,17 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>>>::new(); + record_all_trie_keys::>>, _>( + &mdb, + &root, + &mut proof_recorder, + ) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); 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_header_to_grandpa_pallet::(root); - - FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: bridged_header_hash.into(), - storage_proof, - lane: params.lane, - } + (root, storage_proof) } /// Insert header to the bridge GRANDPA pallet. @@ -154,3 +243,25 @@ where pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); (bridged_block_number, bridged_header_hash) } + +/// Insert header to the bridge parachains pallet. +pub(crate) fn insert_header_to_parachains_pallet( + state_root: bp_runtime::HashOf, +) -> (bp_runtime::BlockNumberOf, bp_runtime::HashOf) +where + R: pallet_bridge_parachains::Config, + PI: 'static, + PC: Chain + Parachain, +{ + let bridged_block_number = Zero::zero(); + let bridged_header = bp_runtime::HeaderOf::::new( + bridged_block_number, + Default::default(), + state_root, + Default::default(), + Default::default(), + ); + let bridged_header_hash = bridged_header.hash(); + pallet_bridge_parachains::initialize_for_benchmarks::(bridged_header); + (bridged_block_number, bridged_header_hash) +} diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 47ab91928c7..06a1f82e7b0 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -33,6 +33,13 @@ use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain, StorageProofErr use frame_support::dispatch::PostDispatchInfo; use sp_std::{marker::PhantomData, vec::Vec}; +#[cfg(feature = "runtime-benchmarks")] +use bp_parachains::ParaStoredHeaderDataBuilder; +#[cfg(feature = "runtime-benchmarks")] +use bp_runtime::HeaderOf; +#[cfg(feature = "runtime-benchmarks")] +use codec::Encode; + // Re-export in crate namespace for `construct_runtime!`. pub use pallet::*; @@ -654,6 +661,25 @@ impl, I: 'static, C: Parachain> HeaderChain } } +/// (Re)initialize pallet with given header for using it in `pallet-bridge-messages` benchmarks. +#[cfg(feature = "runtime-benchmarks")] +pub fn initialize_for_benchmarks, I: 'static, PC: Parachain>( + header: HeaderOf, +) { + let parachain = ParaId(PC::PARACHAIN_ID); + let parachain_head = ParaHead(header.encode()); + let updated_head_data = T::ParaStoredHeaderDataBuilder::try_build(parachain, ¶chain_head) + .expect("failed to build stored parachain head in benchmarks"); + Pallet::::update_parachain_head( + parachain, + None, + 0, + updated_head_data, + parachain_head.hash(), + ) + .expect("failed to insert parachain head in benchmarks"); +} + #[cfg(test)] mod tests { use super::*;