From 0105897ab800c54c68e8f89a5fe536375b31cbd2 Mon Sep 17 00:00:00 2001
From: Muharem Ismailov <ismailov.m.h@gmail.com>
Date: Fri, 30 Jun 2023 20:34:26 +0200
Subject: [PATCH] Runtime: Success value and reachable location for Polkadot
 Collectives benchmarks (#2784)

* Runtime: Success value and reachable location for Polkadot Collectives benchmarks

* separate promote origin for benches

* pay with ensure
---
 .../src/fellowship/mod.rs                     | 19 +++++-
 .../collectives-polkadot/src/impls.rs         | 62 ++++++++++++++++++-
 2 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs
index d3526715344..99613542a2e 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/fellowship/mod.rs
@@ -42,6 +42,9 @@ use sp_runtime::traits::{AccountIdConversion, ConstU16, ConvertToValue, Replace,
 use xcm::latest::BodyId;
 use xcm_builder::{AliasesIntoAccountId32, LocatableAssetId, PayOverXcm};
 
+#[cfg(feature = "runtime-benchmarks")]
+use crate::impls::benchmarks::{OpenHrmpChannel, PayWithEnsure};
+
 /// The Fellowship members' ranks.
 pub mod ranks {
 	use pallet_ranked_collective::Rank;
@@ -105,13 +108,21 @@ pub type FellowshipCollectiveInstance = pallet_ranked_collective::Instance1;
 impl pallet_ranked_collective::Config<FellowshipCollectiveInstance> for Runtime {
 	type WeightInfo = weights::pallet_ranked_collective::WeightInfo<Runtime>;
 	type RuntimeEvent = RuntimeEvent;
+
+	#[cfg(not(feature = "runtime-benchmarks"))]
 	// Promotions and the induction of new members are serviced by `FellowshipCore` pallet instance.
-	type PromoteOrigin = EnsureRootWithSuccess<Self::AccountId, ConstU16<{ ranks::DAN_9 }>>;
+	type PromoteOrigin = frame_system::EnsureNever<pallet_ranked_collective::Rank>;
+	#[cfg(feature = "runtime-benchmarks")]
+	// The maximum value of `u16` set as a success value for the root to ensure the benchmarks will pass.
+	type PromoteOrigin = EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>;
+
 	// Demotion is by any of:
 	// - Root can demote arbitrarily.
 	// - the FellowshipAdmin origin (i.e. token holder referendum);
+	//
+	// The maximum value of `u16` set as a success value for the root to ensure the benchmarks will pass.
 	type DemoteOrigin = EitherOf<
-		EnsureRootWithSuccess<Self::AccountId, ConstU16<{ ranks::DAN_9 }>>,
+		EnsureRootWithSuccess<Self::AccountId, ConstU16<65535>>,
 		MapSuccess<
 			EnsureXcm<IsVoiceOfBody<GovernanceLocation, FellowshipAdminBodyId>>,
 			Replace<ConstU16<{ ranks::DAN_9 }>>,
@@ -211,7 +222,11 @@ pub type FellowshipSalaryPaymaster = PayOverXcm<
 impl pallet_salary::Config<FellowshipSalaryInstance> for Runtime {
 	type WeightInfo = weights::pallet_salary::WeightInfo<Runtime>;
 	type RuntimeEvent = RuntimeEvent;
+
+	#[cfg(not(feature = "runtime-benchmarks"))]
 	type Paymaster = FellowshipSalaryPaymaster;
+	#[cfg(feature = "runtime-benchmarks")]
+	type Paymaster = PayWithEnsure<FellowshipSalaryPaymaster, OpenHrmpChannel<ConstU32<1000>>>;
 	type Members = pallet_ranked_collective::Pallet<Runtime, FellowshipCollectiveInstance>;
 
 	#[cfg(not(feature = "runtime-benchmarks"))]
diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/impls.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/impls.rs
index 6ccff8bda1c..784f6149b81 100644
--- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/impls.rs
+++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/impls.rs
@@ -150,12 +150,17 @@ impl PrivilegeCmp<OriginCaller> for EqualOrGreatestRootCmp {
 #[cfg(feature = "runtime-benchmarks")]
 pub mod benchmarks {
 	use super::*;
-	use frame_support::traits::fungible;
+	use crate::ParachainSystem;
+	use cumulus_primitives_core::{ChannelStatus, GetChannelInfo};
+	use frame_support::traits::{
+		fungible,
+		tokens::{Pay, PaymentStatus},
+	};
 	use pallet_ranked_collective::Rank;
 	use parachains_common::{AccountId, Balance};
 	use sp_runtime::traits::Convert;
 
-	/// Rank to salary conversion helper type.`
+	/// Rank to salary conversion helper type.
 	pub struct RankToSalary<Fungible>(PhantomData<Fungible>);
 	impl<Fungible> Convert<Rank, Balance> for RankToSalary<Fungible>
 	where
@@ -165,4 +170,57 @@ pub mod benchmarks {
 			Balance::from(r).saturating_mul(Fungible::minimum_balance())
 		}
 	}
+
+	/// Trait for setting up any prerequisites for successful execution of benchmarks.
+	pub trait EnsureSuccessful {
+		fn ensure_successful();
+	}
+
+	/// Implementation of the [`EnsureSuccessful`] trait which opens an HRMP channel between
+	/// the Collectives and a parachain with a given ID.
+	pub struct OpenHrmpChannel<I>(PhantomData<I>);
+	impl<I: Get<u32>> EnsureSuccessful for OpenHrmpChannel<I> {
+		fn ensure_successful() {
+			if let ChannelStatus::Closed = ParachainSystem::get_channel_status(I::get().into()) {
+				ParachainSystem::open_outbound_hrmp_channel_for_benchmarks(I::get().into())
+			}
+		}
+	}
+
+	/// Type that wraps a type implementing the [`Pay`] trait to decorate its [`Pay::ensure_successful`]
+	/// function with a provided implementation of the [`EnsureSuccessful`] trait.
+	pub struct PayWithEnsure<O, E>(PhantomData<(O, E)>);
+	impl<O, E> Pay for PayWithEnsure<O, E>
+	where
+		O: Pay,
+		E: EnsureSuccessful,
+	{
+		type AssetKind = O::AssetKind;
+		type Balance = O::Balance;
+		type Beneficiary = O::Beneficiary;
+		type Error = O::Error;
+		type Id = O::Id;
+
+		fn pay(
+			who: &Self::Beneficiary,
+			asset_kind: Self::AssetKind,
+			amount: Self::Balance,
+		) -> Result<Self::Id, Self::Error> {
+			O::pay(who, asset_kind, amount)
+		}
+		fn check_payment(id: Self::Id) -> PaymentStatus {
+			O::check_payment(id)
+		}
+		fn ensure_successful(
+			who: &Self::Beneficiary,
+			asset_kind: Self::AssetKind,
+			amount: Self::Balance,
+		) {
+			E::ensure_successful();
+			O::ensure_successful(who, asset_kind, amount)
+		}
+		fn ensure_concluded(id: Self::Id) {
+			O::ensure_concluded(id)
+		}
+	}
 }
-- 
GitLab