Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Bridge benchmarks for bridge hub rococo/wococo #2107

Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bridges/bin/runtime-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
201 changes: 156 additions & 45 deletions bridges/bin/runtime-common/src/messages_benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,60 +22,54 @@
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,
},
};

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<R, BI, FI, B, BH, BHH>(
///
/// 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<R, FI, B>(
params: MessageProofParams,
) -> (FromBridgedChainMessagesProof<HashOf<BridgedChain<B>>>, Weight)
where
R: frame_system::Config<AccountId = AccountIdOf<ThisChain<B>>>
+ pallet_bridge_grandpa::Config<FI>,
R::BridgedChain: bp_runtime::Chain<Hash = HashOf<BridgedChain<B>>, Header = BH>,
B: MessageBridge,
BI: 'static,
R: pallet_bridge_grandpa::Config<FI, BridgedChain = UnderlyingChainOf<BridgedChain<B>>>,
FI: 'static,
BH: Header<Hash = HashOf<BridgedChain<B>>>,
BHH: Hasher<Out = HashOf<BridgedChain<B>>>,
AccountIdOf<ThisChain<B>>: PartialEq + sp_std::fmt::Debug,
AccountIdOf<BridgedChain<B>>: From<[u8; 32]>,
BalanceOf<ThisChain<B>>: Debug + MaybeSerializeDeserialize,
CallOf<ThisChain<B>>: From<frame_system::Call<R>> + GetDispatchInfo,
HashOf<BridgedChain<B>>: 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::<B>(
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::<R, FI>(state_root);

(
Expand All @@ -90,47 +84,142 @@ 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<R, PI, B>(
params: MessageProofParams,
) -> (FromBridgedChainMessagesProof<HashOf<BridgedChain<B>>>, Weight)
where
R: pallet_bridge_parachains::Config<PI>,
PI: 'static,
B: MessageBridge,
UnderlyingChainOf<BridgedChain<B>>: Chain<Hash = ParaHash> + Parachain,
{
// prepare storage proof
let (state_root, storage_proof) = prepare_messages_storage_proof::<B>(
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::<R, PI, UnderlyingChainOf<BridgedChain<B>>>(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<R, FI, B, BH, BHH>(
///
/// 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<R, FI, B>(
params: MessageDeliveryProofParams<AccountIdOf<ThisChain<B>>>,
) -> FromBridgedChainMessagesDeliveryProof<HashOf<BridgedChain<B>>>
where
R: pallet_bridge_grandpa::Config<FI>,
R::BridgedChain: bp_runtime::Chain<Hash = HashOf<BridgedChain<B>>, Header = BH>,
R: pallet_bridge_grandpa::Config<FI, BridgedChain = UnderlyingChainOf<BridgedChain<B>>>,
FI: 'static,
B: MessageBridge,
BH: Header<Hash = HashOf<BridgedChain<B>>>,
BHH: Hasher<Out = HashOf<BridgedChain<B>>>,
HashOf<BridgedChain<B>>: Copy + Default,
{
// prepare storage proof
let lane = params.lane;
let (state_root, storage_proof) = prepare_message_delivery_proof::<B>(params);

// update runtime storage
let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::<R, FI>(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<R, PI, B>(
params: MessageDeliveryProofParams<AccountIdOf<ThisChain<B>>>,
) -> FromBridgedChainMessagesDeliveryProof<HashOf<BridgedChain<B>>>
where
R: pallet_bridge_parachains::Config<PI>,
PI: 'static,
B: MessageBridge,
UnderlyingChainOf<BridgedChain<B>>: Chain<Hash = ParaHash> + Parachain,
{
// prepare storage proof
let lane = params.lane;
let (state_root, storage_proof) = prepare_message_delivery_proof::<B>(params);

// update runtime storage
let (_, bridged_header_hash) =
insert_header_to_parachains_pallet::<R, PI, UnderlyingChainOf<BridgedChain<B>>>(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<B>(
params: MessageDeliveryProofParams<AccountIdOf<ThisChain<B>>>,
) -> (HashOf<BridgedChain<B>>, RawStorageProof)
where
B: MessageBridge,
{
// prepare Bridged chain storage with inbound lane state
let storage_key =
storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &params.lane).0;
let mut root = Default::default();
let mut mdb = MemoryDB::default();
{
let mut trie = TrieDBMutBuilderV1::<BHH>::new(&mut mdb, &mut root).build();
let mut trie =
TrieDBMutBuilderV1::<HasherOf<BridgedChain<B>>>::new(&mut mdb, &mut root).build();
trie.insert(&storage_key, &params.inbound_lane_data.encode())
.map_err(|_| "TrieMut::insert has failed")
.expect("TrieMut::insert should not fail in benchmarks");
}
root = grow_trie(root, &mut mdb, params.size);

// generate storage proof to be delivered to This chain
let mut proof_recorder = Recorder::<LayoutV1<BHH>>::new();
record_all_trie_keys::<LayoutV1<BHH>, _>(&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::<LayoutV1<HasherOf<BridgedChain<B>>>>::new();
record_all_trie_keys::<LayoutV1<HasherOf<BridgedChain<B>>>, _>(
&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::<R, FI>(root);

FromBridgedChainMessagesDeliveryProof {
bridged_header_hash: bridged_header_hash.into(),
storage_proof,
lane: params.lane,
}
(root, storage_proof)
}

/// Insert header to the bridge GRANDPA pallet.
Expand All @@ -154,3 +243,25 @@ where
pallet_bridge_grandpa::initialize_for_benchmarks::<R, GI>(bridged_header);
(bridged_block_number, bridged_header_hash)
}

/// Insert header to the bridge parachains pallet.
pub(crate) fn insert_header_to_parachains_pallet<R, PI, PC>(
state_root: bp_runtime::HashOf<PC>,
) -> (bp_runtime::BlockNumberOf<PC>, bp_runtime::HashOf<PC>)
where
R: pallet_bridge_parachains::Config<PI>,
PI: 'static,
PC: Chain<Hash = ParaHash> + Parachain,
{
let bridged_block_number = Zero::zero();
let bridged_header = bp_runtime::HeaderOf::<PC>::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::<R, PI, PC>(bridged_header);
(bridged_block_number, bridged_header_hash)
}
26 changes: 26 additions & 0 deletions bridges/modules/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down Expand Up @@ -654,6 +661,25 @@ impl<T: Config<I>, I: 'static, C: Parachain<Hash = ParaHash>> HeaderChain<C>
}
}

/// (Re)initialize pallet with given header for using it in `pallet-bridge-messages` benchmarks.
#[cfg(feature = "runtime-benchmarks")]
pub fn initialize_for_benchmarks<T: Config<I>, I: 'static, PC: Parachain<Hash = ParaHash>>(
header: HeaderOf<PC>,
) {
let parachain = ParaId(PC::PARACHAIN_ID);
let parachain_head = ParaHead(header.encode());
let updated_head_data = T::ParaStoredHeaderDataBuilder::try_build(parachain, &parachain_head)
.expect("failed to build stored parachain head in benchmarks");
Pallet::<T, I>::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::*;
Expand Down
9 changes: 8 additions & 1 deletion parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ bp-bridge-hub-rococo = { path = "../../../../bridges/primitives/chain-bridge-hub
bp-bridge-hub-wococo = { path = "../../../../bridges/primitives/chain-bridge-hub-wococo", default-features = false }
bp-messages = { path = "../../../../bridges/primitives/messages", default-features = false }
bp-parachains = { path = "../../../../bridges/primitives/parachains", default-features = false }
bp-polkadot-core = { path = "../../../../bridges/primitives/polkadot-core", default-features = false }
bp-runtime = { path = "../../../../bridges/primitives/runtime", default-features = false }
bp-rococo = { path = "../../../../bridges/primitives/chain-rococo", default-features = false }
bp-wococo = { path = "../../../../bridges/primitives/chain-wococo", default-features = false }
Expand All @@ -100,6 +101,7 @@ std = [
"bp-bridge-hub-wococo/std",
"bp-messages/std",
"bp-parachains/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"bp-rococo/std",
"bp-wococo/std",
Expand Down Expand Up @@ -159,15 +161,20 @@ std = [
]

runtime-benchmarks = [
"bridge-runtime-common/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-bridge-grandpa/runtime-benchmarks",
"pallet-bridge-messages/runtime-benchmarks",
"pallet-bridge-parachains/runtime-benchmarks",
"pallet-bridge-relayers/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.

//! Bridge definitions that are used on Rococo to bridge with Wococo.

use crate::{
BridgeParachainWococoInstance, ParachainInfo, Runtime, WithBridgeHubWococoMessagesInstance,
XcmBlobHauler, XcmBlobHaulerAdapter, XcmRouter,
Expand All @@ -22,7 +24,10 @@ use bp_messages::{LaneId, MessageNonce};
use bp_runtime::ChainId;
use bridge_runtime_common::{
messages,
messages::{MessageBridge, ThisChainWithMessages, UnderlyingChainProvider},
messages::{
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
MessageBridge, ThisChainWithMessages, UnderlyingChainProvider,
},
};
use frame_support::{parameter_types, RuntimeDebug};
use xcm::{
Expand All @@ -43,6 +48,13 @@ parameter_types! {
pub ActiveOutboundLanesToBridgeHubWococo: &'static [bp_messages::LaneId] = &[DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO];
}

/// Proof of messages, coming from Wococo.
pub type FromWococoBridgeHubMessagesProof =
FromBridgedChainMessagesProof<bp_bridge_hub_wococo::Hash>;
/// Messages delivery proof for Rococo Bridge Hub -> Wococo Bridge Hub messages.
pub type ToWococoBridgeHubMessagesDeliveryProof =
FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_wococo::Hash>;

/// Dispatches received XCM messages from other bridge
pub type OnBridgeHubRococoBlobDispatcher =
BridgeBlobDispatcher<XcmRouter, BridgeHubRococoUniversalLocation>;
Expand Down
Loading