diff --git a/Cargo.lock b/Cargo.lock
index 6c59a5977046..9ed6570945b6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2155,6 +2155,7 @@ dependencies = [
"bp-test-utils",
"bp-xcm-bridge-hub",
"bp-xcm-bridge-hub-router",
+ "frame-benchmarking",
"frame-support",
"frame-system",
"hash-db",
diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml
index 8c3e8c989dbc..2f843c607967 100644
--- a/bridges/bin/runtime-common/Cargo.toml
+++ b/bridges/bin/runtime-common/Cargo.toml
@@ -34,6 +34,7 @@ pallet-bridge-relayers = { path = "../../modules/relayers", default-features = f
# Substrate dependencies
+frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true}
frame-support = { path = "../../../substrate/frame/support", default-features = false }
frame-system = { path = "../../../substrate/frame/system", default-features = false }
pallet-transaction-payment = { path = "../../../substrate/frame/transaction-payment", default-features = false }
@@ -65,6 +66,7 @@ std = [
"bp-xcm-bridge-hub-router/std",
"bp-xcm-bridge-hub/std",
"codec/std",
+ "frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"hash-db/std",
@@ -86,6 +88,7 @@ std = [
"xcm/std",
]
runtime-benchmarks = [
+ "frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs
index bd47d37fc07d..5142d51ed643 100644
--- a/bridges/bin/runtime-common/src/mock.rs
+++ b/bridges/bin/runtime-common/src/mock.rs
@@ -419,3 +419,79 @@ impl BridgedChainWithMessages for BridgedChain {}
pub fn run_test(test: impl FnOnce()) {
sp_io::TestExternalities::new(Default::default()).execute_with(test)
}
+
+/// Run test within test externalities.
+pub fn new_test_ext() -> sp_io::TestExternalities {
+ sp_io::TestExternalities::new(Default::default())
+}
+
+#[cfg(feature = "runtime-benchmarks")]
+impl crate::refund_relayer_extension::ExtBenchmarkingConfig for TestRuntime {
+ fn setup_environment() {
+ crate::refund_relayer_extension::tests::initialize_environment(100, 100, 100);
+ }
+
+ fn run_extension(choice: u32) {
+ use sp_runtime::traits::{DispatchTransaction, TransactionExtension};
+
+ let call = match choice {
+ 0 => crate::refund_relayer_extension::tests::message_delivery_call(200),
+ 1 => crate::refund_relayer_extension::tests::message_confirmation_call(200),
+ _ => unreachable!("only 2 types of messages"),
+ };
+ let mut dispatch_info = crate::refund_relayer_extension::tests::dispatch_info();
+ dispatch_info.weight = Weight::from_parts(
+ frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2,
+ 0,
+ );
+ let pre_dispatch_data = crate::refund_relayer_extension::tests::pre_dispatch_data_get();
+
+ let extension = crate::refund_relayer_extension::tests::parachain_extension();
+ let _ = extension
+ .validate_and_prepare(Some(0).into(), &call, &dispatch_info, 0)
+ .map(|(pre, _)| pre);
+ let _ = crate::refund_relayer_extension::mock::TestExtension::post_dispatch(
+ Some(pre_dispatch_data),
+ &dispatch_info,
+ &frame_support::dispatch::PostDispatchInfo {
+ actual_weight: None,
+ pays_fee: frame_support::dispatch::Pays::Yes,
+ },
+ 1024,
+ &Ok(()),
+ &(),
+ );
+ }
+
+ fn run_grandpa_extension(choice: u32) {
+ use sp_runtime::traits::{DispatchTransaction, TransactionExtension};
+
+ let call = match choice {
+ 0 => crate::refund_relayer_extension::tests::message_delivery_call(200),
+ 1 => crate::refund_relayer_extension::tests::message_confirmation_call(200),
+ _ => unreachable!("only 2 types of messages"),
+ };
+ let mut dispatch_info = crate::refund_relayer_extension::tests::dispatch_info();
+ dispatch_info.weight = Weight::from_parts(
+ frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2,
+ 0,
+ );
+ let pre_dispatch_data = crate::refund_relayer_extension::tests::pre_dispatch_data_get();
+
+ let extension = crate::refund_relayer_extension::tests::grandpa_extension();
+ let _ = extension
+ .validate_and_prepare(Some(0).into(), &call, &dispatch_info, 0)
+ .map(|(pre, _)| pre);
+ let _ = crate::refund_relayer_extension::mock::TestExtension::post_dispatch(
+ Some(pre_dispatch_data),
+ &dispatch_info,
+ &frame_support::dispatch::PostDispatchInfo {
+ actual_weight: None,
+ pays_fee: frame_support::dispatch::Pays::Yes,
+ },
+ 1024,
+ &Ok(()),
+ &(),
+ );
+ }
+}
diff --git a/bridges/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs
deleted file mode 100644
index 66a4d01c3270..000000000000
--- a/bridges/bin/runtime-common/src/refund_relayer_extension.rs
+++ /dev/null
@@ -1,2376 +0,0 @@
-// Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Parity Bridges Common.
-
-// Parity Bridges Common is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Parity Bridges Common is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Parity Bridges Common. If not, see .
-
-//! Signed extension that refunds relayer if he has delivered some new messages.
-//! It also refunds transaction cost if the transaction is an `utility.batchAll()`
-//! with calls that are: delivering new messsage and all necessary underlying headers
-//! (parachain or relay chain).
-
-use crate::messages_call_ext::{
- CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo, MessagesCallSubType,
-};
-use bp_messages::{LaneId, MessageNonce};
-use bp_relayers::{RewardsAccountOwner, RewardsAccountParams};
-use bp_runtime::{Chain, Parachain, ParachainIdOf, RangeInclusiveExt, StaticStrProvider};
-use codec::{Codec, Decode, Encode};
-use frame_support::{
- dispatch::{CallableCallFor, DispatchInfo, PostDispatchInfo},
- traits::IsSubType,
- weights::Weight,
- CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
-};
-use pallet_bridge_grandpa::{
- CallSubType as GrandpaCallSubType, Config as GrandpaConfig, SubmitFinalityProofHelper,
- SubmitFinalityProofInfo,
-};
-use pallet_bridge_messages::Config as MessagesConfig;
-use pallet_bridge_parachains::{
- BoundedBridgeGrandpaConfig, CallSubType as ParachainsCallSubType, Config as ParachainsConfig,
- RelayBlockNumber, SubmitParachainHeadsHelper, SubmitParachainHeadsInfo,
-};
-use pallet_bridge_relayers::{
- Config as RelayersConfig, Pallet as RelayersPallet, WeightInfoExt as _,
-};
-use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTransaction};
-use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet};
-use scale_info::TypeInfo;
-use sp_runtime::{
- traits::{
- AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf,
- TransactionExtension, TransactionExtensionBase, Zero,
- },
- transaction_validity::{
- InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransactionBuilder,
- },
- DispatchResult, FixedPointOperand, RuntimeDebug,
-};
-use sp_std::{marker::PhantomData, vec, vec::Vec};
-
-type AccountIdOf = ::AccountId;
-// without this typedef rustfmt fails with internal err
-type BalanceOf =
- <::OnChargeTransaction as OnChargeTransaction>::Balance;
-type CallOf = ::RuntimeCall;
-
-/// Trait identifying a bridged parachain. A relayer might be refunded for delivering messages
-/// coming from this parachain.
-pub trait RefundableParachainId {
- /// The instance of the bridge parachains pallet.
- type Instance;
- /// The parachain Id.
- type Id: Get;
-}
-
-/// Default implementation of `RefundableParachainId`.
-pub struct DefaultRefundableParachainId(PhantomData<(Instance, Id)>);
-
-impl RefundableParachainId for DefaultRefundableParachainId
-where
- Id: Get,
-{
- type Instance = Instance;
- type Id = Id;
-}
-
-/// Implementation of `RefundableParachainId` for `trait Parachain`.
-pub struct RefundableParachain(PhantomData<(Instance, Para)>);
-
-impl RefundableParachainId for RefundableParachain
-where
- Para: Parachain,
-{
- type Instance = Instance;
- type Id = ParachainIdOf;
-}
-
-/// Trait identifying a bridged messages lane. A relayer might be refunded for delivering messages
-/// coming from this lane.
-pub trait RefundableMessagesLaneId {
- /// The instance of the bridge messages pallet.
- type Instance: 'static;
- /// The messages lane id.
- type Id: Get;
-}
-
-/// Default implementation of `RefundableMessagesLaneId`.
-pub struct RefundableMessagesLane(PhantomData<(Instance, Id)>);
-
-impl RefundableMessagesLaneId for RefundableMessagesLane
-where
- Instance: 'static,
- Id: Get,
-{
- type Instance = Instance;
- type Id = Id;
-}
-
-/// Refund calculator.
-pub trait RefundCalculator {
- // The underlying integer type in which the refund is calculated.
- type Balance;
-
- /// Compute refund for given transaction.
- fn compute_refund(
- info: &DispatchInfo,
- post_info: &PostDispatchInfo,
- len: usize,
- tip: Self::Balance,
- ) -> Self::Balance;
-}
-
-/// `RefundCalculator` implementation which refunds the actual transaction fee.
-pub struct ActualFeeRefund(PhantomData);
-
-impl RefundCalculator for ActualFeeRefund
-where
- R: TransactionPaymentConfig,
- CallOf: Dispatchable,
- BalanceOf: FixedPointOperand,
-{
- type Balance = BalanceOf;
-
- fn compute_refund(
- info: &DispatchInfo,
- post_info: &PostDispatchInfo,
- len: usize,
- tip: BalanceOf,
- ) -> BalanceOf {
- pallet_transaction_payment::Pallet::::compute_actual_fee(len as _, info, post_info, tip)
- }
-}
-
-/// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`.
-#[cfg_attr(test, derive(Debug, PartialEq))]
-pub struct PreDispatchData {
- /// Transaction submitter (relayer) account.
- relayer: AccountId,
- /// Type of the call.
- call_info: CallInfo,
-}
-
-/// Type of the call that the extension recognizes.
-#[derive(RuntimeDebugNoBound, PartialEq)]
-pub enum CallInfo {
- /// Relay chain finality + parachain finality + message delivery/confirmation calls.
- AllFinalityAndMsgs(
- SubmitFinalityProofInfo,
- SubmitParachainHeadsInfo,
- MessagesCallInfo,
- ),
- /// Relay chain finality + message delivery/confirmation calls.
- RelayFinalityAndMsgs(SubmitFinalityProofInfo, MessagesCallInfo),
- /// Parachain finality + message delivery/confirmation calls.
- ///
- /// This variant is used only when bridging with parachain.
- ParachainFinalityAndMsgs(SubmitParachainHeadsInfo, MessagesCallInfo),
- /// Standalone message delivery/confirmation call.
- Msgs(MessagesCallInfo),
-}
-
-impl CallInfo {
- /// Returns true if call is a message delivery call (with optional finality calls).
- fn is_receive_messages_proof_call(&self) -> bool {
- match self.messages_call_info() {
- MessagesCallInfo::ReceiveMessagesProof(_) => true,
- MessagesCallInfo::ReceiveMessagesDeliveryProof(_) => false,
- }
- }
-
- /// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call.
- fn submit_finality_proof_info(&self) -> Option> {
- match *self {
- Self::AllFinalityAndMsgs(info, _, _) => Some(info),
- Self::RelayFinalityAndMsgs(info, _) => Some(info),
- _ => None,
- }
- }
-
- /// Returns the pre-dispatch `SubmitParachainHeadsInfo`.
- fn submit_parachain_heads_info(&self) -> Option<&SubmitParachainHeadsInfo> {
- match self {
- Self::AllFinalityAndMsgs(_, info, _) => Some(info),
- Self::ParachainFinalityAndMsgs(info, _) => Some(info),
- _ => None,
- }
- }
-
- /// Returns the pre-dispatch `ReceiveMessagesProofInfo`.
- fn messages_call_info(&self) -> &MessagesCallInfo {
- match self {
- Self::AllFinalityAndMsgs(_, _, info) => info,
- Self::RelayFinalityAndMsgs(_, info) => info,
- Self::ParachainFinalityAndMsgs(_, info) => info,
- Self::Msgs(info) => info,
- }
- }
-}
-
-/// The actions on relayer account that need to be performed because of his actions.
-#[derive(RuntimeDebug, PartialEq)]
-pub enum RelayerAccountAction {
- /// Do nothing with relayer account.
- None,
- /// Reward the relayer.
- Reward(AccountId, RewardsAccountParams, Reward),
- /// Slash the relayer.
- Slash(AccountId, RewardsAccountParams),
-}
-
-/// Everything common among our refund transaction extensions.
-pub trait RefundTransactionExtension:
- 'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo
-where
- >::BridgedChain:
- Chain,
-{
- /// This chain runtime.
- type Runtime: UtilityConfig>
- + GrandpaConfig
- + MessagesConfig<::Instance>
- + RelayersConfig;
- /// Grandpa pallet reference.
- type GrandpaInstance: 'static;
- /// Messages pallet and lane reference.
- type Msgs: RefundableMessagesLaneId;
- /// Refund amount calculator.
- type Refund: RefundCalculator::Reward>;
- /// Priority boost calculator.
- type Priority: Get;
- /// Signed extension unique identifier.
- type Id: StaticStrProvider;
-
- /// Unpack batch runtime call.
- fn expand_call(call: &CallOf) -> Vec<&CallOf>;
-
- /// Given runtime call, check if it has supported format. Additionally, check if any of
- /// (optionally batched) calls are obsolete and we shall reject the transaction.
- fn parse_and_check_for_obsolete_call(
- call: &CallOf,
- ) -> Result