referrerpolicy=no-referrer-when-downgrade

pallet_bridge_relayers/
benchmarking.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Benchmarks for the relayers Pallet.
18
19#![cfg(feature = "runtime-benchmarks")]
20
21use crate::*;
22
23use frame_benchmarking::v2::*;
24use frame_support::{assert_ok, weights::Weight};
25use frame_system::RawOrigin;
26use sp_runtime::traits::One;
27
28/// Reward amount that is (hopefully) is larger than existential deposit across all chains.
29const REWARD_AMOUNT: u32 = u32::MAX;
30
31/// Pallet we're benchmarking here.
32pub struct Pallet<T: Config<I>, I: 'static = ()>(crate::Pallet<T, I>);
33
34/// Trait that must be implemented by runtime.
35pub trait Config<I: 'static = ()>: crate::Config<I> {
36	/// `T::Reward` to use in benchmarks.
37	fn bench_reward() -> Self::Reward;
38	/// Prepare environment for paying given reward for serving given lane.
39	fn prepare_rewards_account(
40		reward_kind: Self::Reward,
41		reward: Self::RewardBalance,
42	) -> Option<BeneficiaryOf<Self, I>>;
43	/// Give enough balance to given account.
44	fn deposit_account(account: Self::AccountId, balance: Self::Balance);
45}
46
47fn assert_last_event<T: Config<I>, I: 'static>(
48	generic_event: <T as pallet::Config<I>>::RuntimeEvent,
49) {
50	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
51}
52
53#[instance_benchmarks(
54	where
55		BeneficiaryOf<T, I>: From<<T as frame_system::Config>::AccountId>,
56)]
57mod benchmarks {
58	use super::*;
59
60	#[benchmark]
61	fn claim_rewards() {
62		let relayer: T::AccountId = whitelisted_caller();
63		let reward_kind = T::bench_reward();
64		let reward_balance = T::RewardBalance::from(REWARD_AMOUNT);
65		let _ = T::prepare_rewards_account(reward_kind, reward_balance);
66		RelayerRewards::<T, I>::insert(&relayer, reward_kind, reward_balance);
67
68		#[extrinsic_call]
69		_(RawOrigin::Signed(relayer.clone()), reward_kind);
70
71		// we can't check anything here, because `PaymentProcedure` is responsible for
72		// payment logic, so we assume that if call has succeeded, the procedure has
73		// also completed successfully
74		assert_last_event::<T, I>(
75			Event::RewardPaid {
76				relayer: relayer.clone(),
77				reward_kind,
78				reward_balance,
79				beneficiary: relayer.into(),
80			}
81			.into(),
82		);
83	}
84
85	#[benchmark]
86	fn claim_rewards_to() -> Result<(), BenchmarkError> {
87		let relayer: T::AccountId = whitelisted_caller();
88		let reward_kind = T::bench_reward();
89		let reward_balance = T::RewardBalance::from(REWARD_AMOUNT);
90
91		let Some(alternative_beneficiary) = T::prepare_rewards_account(reward_kind, reward_balance)
92		else {
93			return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)));
94		};
95		RelayerRewards::<T, I>::insert(&relayer, reward_kind, reward_balance);
96
97		#[extrinsic_call]
98		_(RawOrigin::Signed(relayer.clone()), reward_kind, alternative_beneficiary.clone());
99
100		// we can't check anything here, because `PaymentProcedure` is responsible for
101		// payment logic, so we assume that if call has succeeded, the procedure has
102		// also completed successfully
103		assert_last_event::<T, I>(
104			Event::RewardPaid {
105				relayer: relayer.clone(),
106				reward_kind,
107				reward_balance,
108				beneficiary: alternative_beneficiary,
109			}
110			.into(),
111		);
112
113		Ok(())
114	}
115
116	#[benchmark]
117	fn register() {
118		let relayer: T::AccountId = whitelisted_caller();
119		let valid_till = frame_system::Pallet::<T>::block_number()
120			.saturating_add(crate::Pallet::<T, I>::required_registration_lease())
121			.saturating_add(One::one())
122			.saturating_add(One::one());
123		T::deposit_account(relayer.clone(), crate::Pallet::<T, I>::required_stake());
124
125		#[extrinsic_call]
126		_(RawOrigin::Signed(relayer.clone()), valid_till);
127
128		assert!(crate::Pallet::<T, I>::is_registration_active(&relayer));
129	}
130
131	#[benchmark]
132	fn deregister() {
133		let relayer: T::AccountId = whitelisted_caller();
134		let valid_till = frame_system::Pallet::<T>::block_number()
135			.saturating_add(crate::Pallet::<T, I>::required_registration_lease())
136			.saturating_add(One::one())
137			.saturating_add(One::one());
138		T::deposit_account(relayer.clone(), crate::Pallet::<T, I>::required_stake());
139		crate::Pallet::<T, I>::register(RawOrigin::Signed(relayer.clone()).into(), valid_till)
140			.unwrap();
141		frame_system::Pallet::<T>::set_block_number(valid_till.saturating_add(One::one()));
142
143		#[extrinsic_call]
144		_(RawOrigin::Signed(relayer.clone()));
145
146		assert!(!crate::Pallet::<T, I>::is_registration_active(&relayer));
147	}
148
149	// Benchmark `slash_and_deregister` method of the pallet. We are adding this weight to
150	// the weight of message delivery call if `BridgeRelayersTransactionExtension` signed extension
151	// is deployed at runtime level.
152	#[benchmark]
153	fn slash_and_deregister() {
154		// prepare and register relayer account
155		let relayer: T::AccountId = whitelisted_caller();
156		let valid_till = frame_system::Pallet::<T>::block_number()
157			.saturating_add(crate::Pallet::<T, I>::required_registration_lease())
158			.saturating_add(One::one())
159			.saturating_add(One::one());
160		T::deposit_account(relayer.clone(), crate::Pallet::<T, I>::required_stake());
161		assert_ok!(crate::Pallet::<T, I>::register(
162			RawOrigin::Signed(relayer.clone()).into(),
163			valid_till
164		));
165
166		// create slash destination account
167		let slash_destination: T::AccountId = whitelisted_caller();
168		T::deposit_account(slash_destination.clone(), Zero::zero());
169
170		#[block]
171		{
172			crate::Pallet::<T, I>::slash_and_deregister(
173				&relayer,
174				bp_relayers::ExplicitOrAccountParams::Explicit::<_, ()>(slash_destination),
175			);
176		}
177
178		assert!(!crate::Pallet::<T, I>::is_registration_active(&relayer));
179	}
180
181	// Benchmark `register_relayer_reward` method of the pallet. We are adding this weight to
182	// the weight of message delivery call if `BridgeRelayersTransactionExtension` signed extension
183	// is deployed at runtime level.
184	#[benchmark]
185	fn register_relayer_reward() {
186		let reward_kind = T::bench_reward();
187		let relayer: T::AccountId = whitelisted_caller();
188
189		#[block]
190		{
191			crate::Pallet::<T, I>::register_relayer_reward(reward_kind, &relayer, One::one());
192		}
193
194		assert_eq!(RelayerRewards::<T, I>::get(relayer, &reward_kind), Some(One::one()));
195	}
196
197	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime);
198}