From 15cb0af58c1178736dd13db9f1602b2a31158cb9 Mon Sep 17 00:00:00 2001
From: Branislav Kontur <bkontur@gmail.com>
Date: Fri, 1 Sep 2023 13:27:18 +0200
Subject: [PATCH] Added short-benchmarks for cumulus (#1183)

* Added short-benchmarks for cumulus

* Added `--bin` flag for short-benchmarks

* fix dependency for short-benchmark-cumulus

* Fixed benchmark with new XCM::V3 `MAX_INSTRUCTIONS_TO_DECODE`

* Fixed benchmark for bridge messages pallets

---------

Co-authored-by: alvicsam <alvicsam@gmail.com>
Co-authored-by: Javier Viola <javier@parity.io>
Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com>
---
 .gitlab/pipeline/build.yml                    | 15 +++-
 .gitlab/pipeline/short-benchmarks.yml         | 62 +++++++++++++
 .../src/messages_benchmarking.rs              | 87 ++++++++++++++-----
 .../modules/messages/src/weights_ext.rs       |  4 +-
 .../bridge-hubs/bridge-hub-rococo/src/lib.rs  | 10 ++-
 5 files changed, 151 insertions(+), 27 deletions(-)

diff --git a/.gitlab/pipeline/build.yml b/.gitlab/pipeline/build.yml
index 6ea153ff6da..636f7e47afa 100644
--- a/.gitlab/pipeline/build.yml
+++ b/.gitlab/pipeline/build.yml
@@ -146,7 +146,7 @@ build-short-benchmark:
     - .run-immediately
     - .collect-artifacts
   script:
-    - cargo build --profile release --locked --features=runtime-benchmarks
+    - cargo build --profile release --locked --features=runtime-benchmarks --bin polkadot
     - mkdir -p artifacts
     - target/release/polkadot --version
     - cp ./target/release/polkadot ./artifacts/
@@ -265,6 +265,19 @@ build-runtime-testing:
     - job: build-runtime-starters
       artifacts: false
 
+build-short-benchmark-cumulus:
+  stage: build
+  extends:
+    - .docker-env
+    - .common-refs
+    - .run-immediately
+    - .collect-artifacts
+  script:
+    - cargo build --profile release --locked --features=runtime-benchmarks --bin polkadot-parachain
+    - mkdir -p artifacts
+    - target/release/polkadot-parachain --version
+    - cp ./target/release/polkadot-parachain ./artifacts/
+
 # substrate
 
 build-linux-substrate:
diff --git a/.gitlab/pipeline/short-benchmarks.yml b/.gitlab/pipeline/short-benchmarks.yml
index 2993338cabb..81601fba32a 100644
--- a/.gitlab/pipeline/short-benchmarks.yml
+++ b/.gitlab/pipeline/short-benchmarks.yml
@@ -2,6 +2,9 @@
 # Here are all jobs that are executed during "short-benchmarks" stage
 
 # Run all pallet benchmarks only once to check if there are any errors
+
+# run short-benchmarks for relay chain runtimes from polkadot
+
 short-benchmark-polkadot: &short-bench
   stage: short-benchmarks
   extends:
@@ -12,6 +15,8 @@ short-benchmark-polkadot: &short-bench
       artifacts: true
   variables:
     RUNTIME: polkadot
+  tags:
+    - benchmark
   script:
     - ./artifacts/polkadot benchmark pallet --execution wasm --wasm-execution compiled --chain $RUNTIME-dev --pallet "*" --extrinsic "*" --steps 2 --repeat 1
 
@@ -24,3 +29,60 @@ short-benchmark-westend:
   <<: *short-bench
   variables:
     RUNTIME: westend
+
+# run short-benchmarks for system parachain runtimes from cumulus
+
+.short-benchmark-cumulus: &short-bench-cumulus
+  stage: short-benchmarks
+  extends:
+    - .common-refs
+    - .docker-env
+  needs:
+    - job: build-short-benchmark-cumulus
+      artifacts: true
+  variables:
+    RUNTIME_CHAIN: benchmarked-runtime-chain
+  tags:
+    - benchmark
+  script:
+    - ./artifacts/polkadot-parachain benchmark pallet --wasm-execution compiled --chain $RUNTIME_CHAIN --pallet "*" --extrinsic "*" --steps 2 --repeat 1
+
+short-benchmark-asset-hub-polkadot:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: asset-hub-polkadot-dev
+
+short-benchmark-asset-hub-kusama:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: asset-hub-kusama-dev
+
+short-benchmark-asset-hub-westend:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: asset-hub-westend-dev
+
+short-benchmark-bridge-hub-polkadot:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: bridge-hub-polkadot-dev
+
+short-benchmark-bridge-hub-kusama:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: bridge-hub-kusama-dev
+
+short-benchmark-bridge-hub-rococo:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: bridge-hub-rococo-dev
+
+short-benchmark-collectives-polkadot:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: collectives-polkadot-dev
+
+short-benchmark-glutton-kusama:
+  <<: *short-bench-cumulus
+  variables:
+    RUNTIME_CHAIN: glutton-kusama-dev-1300
diff --git a/cumulus/bridges/bin/runtime-common/src/messages_benchmarking.rs b/cumulus/bridges/bin/runtime-common/src/messages_benchmarking.rs
index 60f4bb17858..d80a88f1068 100644
--- a/cumulus/bridges/bin/runtime-common/src/messages_benchmarking.rs
+++ b/cumulus/bridges/bin/runtime-common/src/messages_benchmarking.rs
@@ -29,7 +29,7 @@ use crate::{
 	},
 };
 
-use bp_messages::storage_keys;
+use bp_messages::{storage_keys, MessagePayload};
 use bp_polkadot_core::parachains::ParaHash;
 use bp_runtime::{
 	record_all_trie_keys, Chain, Parachain, RawStorageProof, StorageProofSize, UnderlyingChainOf,
@@ -45,8 +45,8 @@ use xcm::v3::prelude::*;
 /// Prepare inbound bridge message according to given message proof parameters.
 fn prepare_inbound_message(
 	params: &MessageProofParams,
-	destination: InteriorMultiLocation,
-) -> Vec<u8> {
+	successful_dispatch_message_generator: impl Fn(usize) -> MessagePayload,
+) -> MessagePayload {
 	// we only care about **this** message size when message proof needs to be `Minimal`
 	let expected_size = match params.size {
 		StorageProofSize::Minimal(size) => size as usize,
@@ -58,20 +58,15 @@ fn prepare_inbound_message(
 		return vec![0u8; expected_size]
 	}
 
-	// else let's prepare successful message. For XCM bridge hubs, it is the message that
-	// will be pushed further to some XCM queue (XCMP/UMP)
-	let location = xcm::VersionedInteriorMultiLocation::V3(destination);
-	let location_encoded_size = location.encoded_size();
-
-	// we don't need to be super-precise with `expected_size` here
-	let xcm_size = expected_size.saturating_sub(location_encoded_size);
-	let xcm = xcm::VersionedXcm::<()>::V3(vec![Instruction::ClearOrigin; xcm_size].into());
-
-	// this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor
-	// or public fields, so just tuple
-	// (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed
-	// to the storage)
-	(location, xcm).encode().encode()
+	// else let's prepare successful message.
+	let msg = successful_dispatch_message_generator(expected_size);
+	assert!(
+		msg.len() >= expected_size,
+		"msg.len(): {} does not match expected_size: {}",
+		expected_size,
+		msg.len()
+	);
+	msg
 }
 
 /// Prepare proof of messages for the `receive_messages_proof` call.
@@ -84,7 +79,7 @@ fn prepare_inbound_message(
 /// function.
 pub fn prepare_message_proof_from_grandpa_chain<R, FI, B>(
 	params: MessageProofParams,
-	message_destination: InteriorMultiLocation,
+	message_generator: impl Fn(usize) -> MessagePayload,
 ) -> (FromBridgedChainMessagesProof<HashOf<BridgedChain<B>>>, Weight)
 where
 	R: pallet_bridge_grandpa::Config<FI, BridgedChain = UnderlyingChainOf<BridgedChain<B>>>,
@@ -97,7 +92,7 @@ where
 		params.message_nonces.clone(),
 		params.outbound_lane_data.clone(),
 		params.size,
-		prepare_inbound_message(&params, message_destination),
+		prepare_inbound_message(&params, message_generator),
 		encode_all_messages,
 		encode_lane_data,
 	);
@@ -127,7 +122,7 @@ where
 /// `prepare_message_proof_from_grandpa_chain` function.
 pub fn prepare_message_proof_from_parachain<R, PI, B>(
 	params: MessageProofParams,
-	message_destination: InteriorMultiLocation,
+	message_generator: impl Fn(usize) -> MessagePayload,
 ) -> (FromBridgedChainMessagesProof<HashOf<BridgedChain<B>>>, Weight)
 where
 	R: pallet_bridge_parachains::Config<PI>,
@@ -141,7 +136,7 @@ where
 		params.message_nonces.clone(),
 		params.outbound_lane_data.clone(),
 		params.size,
-		prepare_inbound_message(&params, message_destination),
+		prepare_inbound_message(&params, message_generator),
 		encode_all_messages,
 		encode_lane_data,
 	);
@@ -291,3 +286,53 @@ where
 	pallet_bridge_parachains::initialize_for_benchmarks::<R, PI, PC>(bridged_header);
 	(bridged_block_number, bridged_header_hash)
 }
+
+/// Returns callback which generates `BridgeMessage` from Polkadot XCM builder based on
+/// `expected_message_size` for benchmark.
+pub fn generate_xcm_builder_bridge_message_sample(
+	destination: InteriorMultiLocation,
+) -> impl Fn(usize) -> MessagePayload {
+	move |expected_message_size| -> MessagePayload {
+		// For XCM bridge hubs, it is the message that
+		// will be pushed further to some XCM queue (XCMP/UMP)
+		let location = xcm::VersionedInteriorMultiLocation::V3(destination);
+		let location_encoded_size = location.encoded_size();
+
+		// we don't need to be super-precise with `expected_size` here
+		let xcm_size = expected_message_size.saturating_sub(location_encoded_size);
+		let xcm_data_size = xcm_size.saturating_sub(
+			// minus empty instruction size
+			xcm::v3::Instruction::<()>::ExpectPallet {
+				index: 0,
+				name: vec![],
+				module_name: vec![],
+				crate_major: 0,
+				min_crate_minor: 0,
+			}
+			.encoded_size(),
+		);
+
+		log::trace!(
+			target: "runtime::bridge-benchmarks",
+			"generate_xcm_builder_bridge_message_sample with expected_message_size: {}, location_encoded_size: {}, xcm_size: {}, xcm_data_size: {}",
+			expected_message_size, location_encoded_size, xcm_size, xcm_data_size,
+		);
+
+		let xcm = xcm::VersionedXcm::<()>::V3(
+			vec![xcm::v3::Instruction::<()>::ExpectPallet {
+				index: 0,
+				name: vec![42; xcm_data_size],
+				module_name: vec![],
+				crate_major: 0,
+				min_crate_minor: 0,
+			}]
+			.into(),
+		);
+
+		// this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor
+		// or public fields, so just tuple
+		// (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed
+		// to the storage)
+		(location, xcm).encode().encode()
+	}
+}
diff --git a/cumulus/bridges/modules/messages/src/weights_ext.rs b/cumulus/bridges/modules/messages/src/weights_ext.rs
index 1be24a738a4..aeb3a581a69 100644
--- a/cumulus/bridges/modules/messages/src/weights_ext.rs
+++ b/cumulus/bridges/modules/messages/src/weights_ext.rs
@@ -29,8 +29,8 @@ pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128;
 /// calls we're checking here would fit 1KB.
 const SIGNED_EXTENSIONS_SIZE: u32 = 1024;
 
-/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
-/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie.
+/// Number of extra bytes (excluding size of storage value itself) of storage proof.
+/// This mostly depends on number of entries (and their density) in the storage trie.
 /// Some reserve is reserved to account future chain growth.
 pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024;
 
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
index db53867f094..a872e232730 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs
@@ -1040,7 +1040,11 @@ impl_runtime_apis! {
 			type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
 			type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;
 
-			use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_parachain, prepare_message_proof_from_parachain};
+			use bridge_runtime_common::messages_benchmarking::{
+				prepare_message_delivery_proof_from_parachain,
+				prepare_message_proof_from_parachain,
+				generate_xcm_builder_bridge_message_sample,
+			};
 			use pallet_bridge_messages::benchmarking::{
 				Config as BridgeMessagesConfig,
 				Pallet as BridgeMessagesBench,
@@ -1072,7 +1076,7 @@ impl_runtime_apis! {
 						Runtime,
 						BridgeGrandpaWococoInstance,
 						bridge_hub_rococo_config::WithBridgeHubWococoMessageBridge,
-					>(params, X2(GlobalConsensus(Rococo), Parachain(42)))
+					>(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(Rococo), Parachain(42))))
 				}
 
 				fn prepare_message_delivery_proof(
@@ -1115,7 +1119,7 @@ impl_runtime_apis! {
 						Runtime,
 						BridgeGrandpaRococoInstance,
 						bridge_hub_wococo_config::WithBridgeHubRococoMessageBridge,
-					>(params, X2(GlobalConsensus(Wococo), Parachain(42)))
+					>(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(Wococo), Parachain(42))))
 				}
 
 				fn prepare_message_delivery_proof(
-- 
GitLab