mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 17:01:09 +00:00
RefundRelayerForMessagesFromParachain improvements (#1895)
* RefundRelayerForMessagesFromParachain changes - some renamings and cosmetics - removing the GI generic param since we can get it from the parachains config - merging (Parachains Instance, Parachain Id) and (Messages Instance, Messages lane Id) generic params - removing unnecessay derives - renaming for the `TransactionFeeCalculation` and defining `ActualFeeRefund` concrete implementation - adding support for multiple RefundRelayerForMessagesFromParachain (by adding a `StaticStrProvider` generic param) * Revert to using RuntimeDebug
This commit is contained in:
committed by
Bastian Köcher
parent
1d6e8a9a26
commit
623bd85a5e
@@ -80,7 +80,13 @@ pub use pallet_sudo::Call as SudoCall;
|
|||||||
pub use pallet_timestamp::Call as TimestampCall;
|
pub use pallet_timestamp::Call as TimestampCall;
|
||||||
pub use pallet_xcm::Call as XcmCall;
|
pub use pallet_xcm::Call as XcmCall;
|
||||||
|
|
||||||
use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages;
|
use bridge_runtime_common::{
|
||||||
|
generate_bridge_reject_obsolete_headers_and_messages,
|
||||||
|
refund_relayer_extension::{
|
||||||
|
ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane,
|
||||||
|
RefundableParachain,
|
||||||
|
},
|
||||||
|
};
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
pub use sp_runtime::BuildStorage;
|
pub use sp_runtime::BuildStorage;
|
||||||
pub use sp_runtime::{Perbill, Permill};
|
pub use sp_runtime::{Perbill, Permill};
|
||||||
@@ -582,17 +588,15 @@ generate_bridge_reject_obsolete_headers_and_messages! {
|
|||||||
BridgeRialtoMessages, BridgeRialtoParachainMessages
|
BridgeRialtoMessages, BridgeRialtoParachainMessages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs);
|
||||||
/// Signed extension that refunds relayers that are delivering messages from the Rialto parachain.
|
/// Signed extension that refunds relayers that are delivering messages from the Rialto parachain.
|
||||||
pub type BridgeRefundRialtoParachainRelayers =
|
pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages<
|
||||||
bridge_runtime_common::refund_relayer_extension::RefundRelayerForMessagesFromParachain<
|
Runtime,
|
||||||
Runtime,
|
RefundableParachain<WithRialtoParachainsInstance, RialtoParachainId>,
|
||||||
RialtoGrandpaInstance,
|
RefundableMessagesLane<WithRialtoParachainMessagesInstance, RialtoParachainMessagesLane>,
|
||||||
WithRialtoParachainsInstance,
|
ActualFeeRefund<Runtime>,
|
||||||
WithRialtoParachainMessagesInstance,
|
StrBridgeRefundRialtoPara2000Lane0Msgs,
|
||||||
RialtoParachainId,
|
>;
|
||||||
RialtoParachainMessagesLane,
|
|
||||||
Runtime,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// The address format for describing accounts.
|
/// The address format for describing accounts.
|
||||||
pub type Address = AccountId;
|
pub type Address = AccountId;
|
||||||
@@ -615,7 +619,7 @@ pub type SignedExtra = (
|
|||||||
frame_system::CheckWeight<Runtime>,
|
frame_system::CheckWeight<Runtime>,
|
||||||
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
|
||||||
BridgeRejectObsoleteHeadersAndMessages,
|
BridgeRejectObsoleteHeadersAndMessages,
|
||||||
BridgeRefundRialtoParachainRelayers,
|
BridgeRefundRialtoParachainMessages,
|
||||||
);
|
);
|
||||||
/// The payload being signed in transactions.
|
/// The payload being signed in transactions.
|
||||||
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
|
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ use crate::messages::{
|
|||||||
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
||||||
};
|
};
|
||||||
use bp_messages::{LaneId, MessageNonce};
|
use bp_messages::{LaneId, MessageNonce};
|
||||||
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
|
use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug};
|
||||||
use pallet_bridge_messages::{Config, Pallet};
|
use pallet_bridge_messages::{Config, Pallet};
|
||||||
use sp_runtime::{transaction_validity::TransactionValidity, RuntimeDebug};
|
use sp_runtime::transaction_validity::TransactionValidity;
|
||||||
|
|
||||||
/// Info about a `ReceiveMessagesProof` call which tries to update a single lane.
|
/// Info about a `ReceiveMessagesProof` call which tries to update a single lane.
|
||||||
#[derive(Copy, Clone, PartialEq, RuntimeDebug)]
|
#[derive(PartialEq, RuntimeDebug)]
|
||||||
pub struct ReceiveMessagesProofInfo {
|
pub struct ReceiveMessagesProofInfo {
|
||||||
pub lane_id: LaneId,
|
pub lane_id: LaneId,
|
||||||
pub best_proof_nonce: MessageNonce,
|
pub best_proof_nonce: MessageNonce,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use crate::messages_call_ext::{
|
|||||||
MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo,
|
MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo,
|
||||||
};
|
};
|
||||||
use bp_messages::LaneId;
|
use bp_messages::LaneId;
|
||||||
|
use bp_runtime::StaticStrProvider;
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo},
|
dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo},
|
||||||
@@ -46,28 +47,77 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
use sp_std::{marker::PhantomData, vec, vec::Vec};
|
use sp_std::{marker::PhantomData, vec, vec::Vec};
|
||||||
|
|
||||||
// TODO (https://github.com/paritytech/parity-bridges-common/issues/1667):
|
// without this typedef rustfmt fails with internal err
|
||||||
// support multiple bridges in this extension
|
type BalanceOf<R> =
|
||||||
|
<<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance;
|
||||||
|
type CallOf<R> = <R as frame_system::Config>::RuntimeCall;
|
||||||
|
|
||||||
/// Transaction fee calculation.
|
/// Trait identifying a bridged parachain. A relayer might be refunded for delivering messages
|
||||||
pub trait TransactionFeeCalculation<Balance> {
|
/// coming from this parachain.
|
||||||
/// Compute fee that is paid for given transaction. The fee is later refunded to relayer.
|
trait RefundableParachainId {
|
||||||
fn compute_fee(
|
/// The instance of the bridge parachains pallet.
|
||||||
|
type Instance;
|
||||||
|
/// The parachain Id.
|
||||||
|
type Id: Get<u32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default implementation of `RefundableParachainId`.
|
||||||
|
pub struct RefundableParachain<Instance, Id>(PhantomData<(Instance, Id)>);
|
||||||
|
|
||||||
|
impl<Instance, Id> RefundableParachainId for RefundableParachain<Instance, Id>
|
||||||
|
where
|
||||||
|
Id: Get<u32>,
|
||||||
|
{
|
||||||
|
type Instance = Instance;
|
||||||
|
type Id = Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait identifying a bridged messages lane. A relayer might be refunded for delivering messages
|
||||||
|
/// coming from this lane.
|
||||||
|
trait RefundableMessagesLaneId {
|
||||||
|
/// The instance of the bridge messages pallet.
|
||||||
|
type Instance;
|
||||||
|
/// The messages lane id.
|
||||||
|
type Id: Get<LaneId>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default implementation of `RefundableMessagesLaneId`.
|
||||||
|
pub struct RefundableMessagesLane<Instance, Id>(PhantomData<(Instance, Id)>);
|
||||||
|
|
||||||
|
impl<Instance, Id> RefundableMessagesLaneId for RefundableMessagesLane<Instance, Id>
|
||||||
|
where
|
||||||
|
Id: Get<LaneId>,
|
||||||
|
{
|
||||||
|
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,
|
info: &DispatchInfo,
|
||||||
post_info: &PostDispatchInfo,
|
post_info: &PostDispatchInfo,
|
||||||
len: usize,
|
len: usize,
|
||||||
tip: Balance,
|
tip: Self::Balance,
|
||||||
) -> Balance;
|
) -> Self::Balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> TransactionFeeCalculation<BalanceOf<R>> for R
|
/// `RefundCalculator` implementation which refunds the actual transaction fee.
|
||||||
|
pub struct ActualFeeRefund<R>(PhantomData<R>);
|
||||||
|
|
||||||
|
impl<R> RefundCalculator for ActualFeeRefund<R>
|
||||||
where
|
where
|
||||||
R: TransactionPaymentConfig,
|
R: TransactionPaymentConfig,
|
||||||
<R as frame_system::Config>::RuntimeCall:
|
CallOf<R>: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
|
||||||
Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
|
|
||||||
BalanceOf<R>: FixedPointOperand,
|
BalanceOf<R>: FixedPointOperand,
|
||||||
{
|
{
|
||||||
fn compute_fee(
|
type Balance = BalanceOf<R>;
|
||||||
|
|
||||||
|
fn compute_refund(
|
||||||
info: &DispatchInfo,
|
info: &DispatchInfo,
|
||||||
post_info: &PostDispatchInfo,
|
post_info: &PostDispatchInfo,
|
||||||
len: usize,
|
len: usize,
|
||||||
@@ -77,7 +127,55 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signed extension that refunds relayer for new messages coming from the parachain.
|
/// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`.
|
||||||
|
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||||
|
pub struct PreDispatchData<AccountId> {
|
||||||
|
/// 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 calls.
|
||||||
|
AllFinalityAndDelivery(RelayBlockNumber, SubmitParachainHeadsInfo, ReceiveMessagesProofInfo),
|
||||||
|
/// Parachain finality + message delivery calls.
|
||||||
|
ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo),
|
||||||
|
/// Standalone message delivery call.
|
||||||
|
Delivery(ReceiveMessagesProofInfo),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CallInfo {
|
||||||
|
/// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call.
|
||||||
|
fn submit_finality_proof_info(&self) -> Option<RelayBlockNumber> {
|
||||||
|
match *self {
|
||||||
|
Self::AllFinalityAndDelivery(info, _, _) => Some(info),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the pre-dispatch `SubmitParachainHeadsInfo`.
|
||||||
|
fn submit_parachain_heads_info(&self) -> Option<&SubmitParachainHeadsInfo> {
|
||||||
|
match self {
|
||||||
|
Self::AllFinalityAndDelivery(_, info, _) => Some(info),
|
||||||
|
Self::ParachainFinalityAndDelivery(info, _) => Some(info),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the pre-dispatch `ReceiveMessagesProofInfo`.
|
||||||
|
fn receive_messages_proof_info(&self) -> &ReceiveMessagesProofInfo {
|
||||||
|
match self {
|
||||||
|
Self::AllFinalityAndDelivery(_, _, info) => info,
|
||||||
|
Self::ParachainFinalityAndDelivery(_, info) => info,
|
||||||
|
Self::Delivery(info) => info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Signed extension that refunds a relayer for new messages coming from a parachain.
|
||||||
///
|
///
|
||||||
/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`)
|
/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`)
|
||||||
/// with message delivery transaction. Batch may deliver either both relay chain header and
|
/// with message delivery transaction. Batch may deliver either both relay chain header and
|
||||||
@@ -86,29 +184,29 @@ where
|
|||||||
///
|
///
|
||||||
/// Extension does not refund transaction tip due to security reasons.
|
/// Extension does not refund transaction tip due to security reasons.
|
||||||
#[derive(
|
#[derive(
|
||||||
|
DefaultNoBound,
|
||||||
CloneNoBound,
|
CloneNoBound,
|
||||||
Decode,
|
Decode,
|
||||||
DefaultNoBound,
|
|
||||||
Encode,
|
Encode,
|
||||||
EqNoBound,
|
EqNoBound,
|
||||||
PartialEqNoBound,
|
PartialEqNoBound,
|
||||||
RuntimeDebugNoBound,
|
RuntimeDebugNoBound,
|
||||||
TypeInfo,
|
TypeInfo,
|
||||||
)]
|
)]
|
||||||
#[scale_info(skip_type_params(RT, GI, PI, MI, PID, LID, FEE))]
|
#[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Id))]
|
||||||
pub struct RefundRelayerForMessagesFromParachain<RT, GI, PI, MI, PID, LID, FEE>(
|
pub struct RefundBridgedParachainMessages<Runtime, Para, Msgs, Refund, Id>(
|
||||||
PhantomData<(RT, GI, PI, MI, PID, LID, FEE)>,
|
PhantomData<(Runtime, Para, Msgs, Refund, Id)>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<R, GI, PI, MI, PID, LID, FEE>
|
impl<Runtime, Para, Msgs, Refund, Id>
|
||||||
RefundRelayerForMessagesFromParachain<R, GI, PI, MI, PID, LID, FEE>
|
RefundBridgedParachainMessages<Runtime, Para, Msgs, Refund, Id>
|
||||||
where
|
where
|
||||||
R: UtilityConfig<RuntimeCall = CallOf<R>>,
|
Runtime: UtilityConfig<RuntimeCall = CallOf<Runtime>>,
|
||||||
CallOf<R>: IsSubType<CallableCallFor<UtilityPallet<R>, R>>,
|
CallOf<Runtime>: IsSubType<CallableCallFor<UtilityPallet<Runtime>, Runtime>>,
|
||||||
{
|
{
|
||||||
fn expand_call<'a>(&self, call: &'a CallOf<R>) -> Option<Vec<&'a CallOf<R>>> {
|
fn expand_call<'a>(&self, call: &'a CallOf<Runtime>) -> Option<Vec<&'a CallOf<Runtime>>> {
|
||||||
let calls = match call.is_sub_type() {
|
let calls = match call.is_sub_type() {
|
||||||
Some(UtilityCall::<R>::batch_all { ref calls }) => {
|
Some(UtilityCall::<Runtime>::batch_all { ref calls }) => {
|
||||||
if calls.len() > 3 {
|
if calls.len() > 3 {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
@@ -123,71 +221,30 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`.
|
impl<Runtime, Para, Msgs, Refund, Id> SignedExtension
|
||||||
#[derive(PartialEq)]
|
for RefundBridgedParachainMessages<Runtime, Para, Msgs, Refund, Id>
|
||||||
#[cfg_attr(test, derive(Debug))]
|
|
||||||
pub struct PreDispatchData<AccountId> {
|
|
||||||
/// Transaction submitter (relayer) account.
|
|
||||||
relayer: AccountId,
|
|
||||||
/// Type of the call.
|
|
||||||
pub call_type: CallType,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type of the call that the extension recognizes.
|
|
||||||
#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)]
|
|
||||||
pub enum CallType {
|
|
||||||
/// Relay chain finality + parachain finality + message delivery calls.
|
|
||||||
AllFinalityAndDelivery(RelayBlockNumber, SubmitParachainHeadsInfo, ReceiveMessagesProofInfo),
|
|
||||||
/// Parachain finality + message delivery calls.
|
|
||||||
ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo),
|
|
||||||
/// Standalone message delivery call.
|
|
||||||
Delivery(ReceiveMessagesProofInfo),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CallType {
|
|
||||||
/// Returns the pre-dispatch messages pallet state.
|
|
||||||
fn receive_messages_proof_info(&self) -> ReceiveMessagesProofInfo {
|
|
||||||
match *self {
|
|
||||||
Self::AllFinalityAndDelivery(_, _, info) => info,
|
|
||||||
Self::ParachainFinalityAndDelivery(_, info) => info,
|
|
||||||
Self::Delivery(info) => info,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// without this typedef rustfmt fails with internal err
|
|
||||||
type BalanceOf<R> =
|
|
||||||
<<R as TransactionPaymentConfig>::OnChargeTransaction as OnChargeTransaction<R>>::Balance;
|
|
||||||
type CallOf<R> = <R as frame_system::Config>::RuntimeCall;
|
|
||||||
|
|
||||||
impl<R, GI, PI, MI, PID, LID, FEE> SignedExtension
|
|
||||||
for RefundRelayerForMessagesFromParachain<R, GI, PI, MI, PID, LID, FEE>
|
|
||||||
where
|
where
|
||||||
R: 'static
|
Self: 'static + Send + Sync,
|
||||||
+ Send
|
Runtime: UtilityConfig<RuntimeCall = CallOf<Runtime>>
|
||||||
+ Sync
|
+ BoundedBridgeGrandpaConfig<Runtime::BridgesGrandpaPalletInstance>
|
||||||
+ UtilityConfig<RuntimeCall = CallOf<R>>
|
+ ParachainsConfig<Para::Instance>
|
||||||
+ BoundedBridgeGrandpaConfig<GI>
|
+ MessagesConfig<Msgs::Instance>
|
||||||
+ ParachainsConfig<PI, BridgesGrandpaPalletInstance = GI>
|
|
||||||
+ MessagesConfig<MI>
|
|
||||||
+ RelayersConfig,
|
+ RelayersConfig,
|
||||||
GI: 'static + Send + Sync,
|
Para: RefundableParachainId,
|
||||||
PI: 'static + Send + Sync,
|
Msgs: RefundableMessagesLaneId,
|
||||||
MI: 'static + Send + Sync,
|
Refund: RefundCalculator<Balance = Runtime::Reward>,
|
||||||
PID: 'static + Send + Sync + Get<u32>,
|
Id: StaticStrProvider,
|
||||||
LID: 'static + Send + Sync + Get<LaneId>,
|
CallOf<Runtime>: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
|
||||||
FEE: 'static + Send + Sync + TransactionFeeCalculation<<R as RelayersConfig>::Reward>,
|
+ IsSubType<CallableCallFor<UtilityPallet<Runtime>, Runtime>>
|
||||||
CallOf<R>: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
|
+ GrandpaCallSubType<Runtime, Runtime::BridgesGrandpaPalletInstance>
|
||||||
+ IsSubType<CallableCallFor<UtilityPallet<R>, R>>
|
+ ParachainsCallSubType<Runtime, Para::Instance>
|
||||||
+ GrandpaCallSubType<R, GI>
|
+ MessagesCallSubType<Runtime, Msgs::Instance>,
|
||||||
+ ParachainsCallSubType<R, PI>
|
|
||||||
+ MessagesCallSubType<R, MI>,
|
|
||||||
{
|
{
|
||||||
const IDENTIFIER: &'static str = "RefundRelayerForMessagesFromParachain";
|
const IDENTIFIER: &'static str = Id::STR;
|
||||||
type AccountId = R::AccountId;
|
type AccountId = Runtime::AccountId;
|
||||||
type Call = CallOf<R>;
|
type Call = CallOf<Runtime>;
|
||||||
type AdditionalSigned = ();
|
type AdditionalSigned = ();
|
||||||
type Pre = Option<PreDispatchData<R::AccountId>>;
|
type Pre = Option<PreDispatchData<Runtime::AccountId>>;
|
||||||
|
|
||||||
fn additional_signed(&self) -> Result<(), TransactionValidityError> {
|
fn additional_signed(&self) -> Result<(), TransactionValidityError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -200,15 +257,12 @@ where
|
|||||||
_info: &DispatchInfoOf<Self::Call>,
|
_info: &DispatchInfoOf<Self::Call>,
|
||||||
_len: usize,
|
_len: usize,
|
||||||
) -> TransactionValidity {
|
) -> TransactionValidity {
|
||||||
let calls = match self.expand_call(call) {
|
if let Some(calls) = self.expand_call(call) {
|
||||||
Some(calls) => calls,
|
for nested_call in calls {
|
||||||
None => return Ok(ValidTransaction::default()),
|
nested_call.check_obsolete_submit_finality_proof()?;
|
||||||
};
|
nested_call.check_obsolete_submit_parachain_heads()?;
|
||||||
|
nested_call.check_obsolete_receive_messages_proof()?;
|
||||||
for call in calls {
|
}
|
||||||
call.check_obsolete_submit_finality_proof()?;
|
|
||||||
call.check_obsolete_submit_parachain_heads()?;
|
|
||||||
call.check_obsolete_receive_messages_proof()?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ValidTransaction::default())
|
Ok(ValidTransaction::default())
|
||||||
@@ -225,35 +279,35 @@ where
|
|||||||
self.validate(who, call, info, len).map(drop)?;
|
self.validate(who, call, info, len).map(drop)?;
|
||||||
|
|
||||||
// Try to check if the tx matches one of types we support.
|
// Try to check if the tx matches one of types we support.
|
||||||
let parse_call_type = || {
|
let parse_call = || {
|
||||||
let mut calls = self.expand_call(call)?.into_iter();
|
let mut calls = self.expand_call(call)?.into_iter();
|
||||||
match calls.len() {
|
match calls.len() {
|
||||||
3 => Some(CallType::AllFinalityAndDelivery(
|
3 => Some(CallInfo::AllFinalityAndDelivery(
|
||||||
calls.next()?.submit_finality_proof_info()?,
|
calls.next()?.submit_finality_proof_info()?,
|
||||||
calls.next()?.submit_parachain_heads_info_for(PID::get())?,
|
calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?,
|
||||||
calls.next()?.receive_messages_proof_info_for(LID::get())?,
|
calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?,
|
||||||
)),
|
)),
|
||||||
2 => Some(CallType::ParachainFinalityAndDelivery(
|
2 => Some(CallInfo::ParachainFinalityAndDelivery(
|
||||||
calls.next()?.submit_parachain_heads_info_for(PID::get())?,
|
calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?,
|
||||||
calls.next()?.receive_messages_proof_info_for(LID::get())?,
|
calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?,
|
||||||
)),
|
)),
|
||||||
1 => Some(CallType::Delivery(
|
1 => Some(CallInfo::Delivery(
|
||||||
calls.next()?.receive_messages_proof_info_for(LID::get())?,
|
calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?,
|
||||||
)),
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(parse_call_type().map(|call_type| {
|
Ok(parse_call().map(|call_info| {
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "runtime::bridge",
|
target: "runtime::bridge",
|
||||||
"RefundRelayerForMessagesFromParachain from parachain {} via {:?} \
|
"{} from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}",
|
||||||
parsed bridge transaction in pre-dispatch: {:?}",
|
Self::IDENTIFIER,
|
||||||
PID::get(),
|
Para::Id::get(),
|
||||||
LID::get(),
|
Msgs::Id::get(),
|
||||||
call_type,
|
call_info,
|
||||||
);
|
);
|
||||||
PreDispatchData { relayer: who.clone(), call_type }
|
PreDispatchData { relayer: who.clone(), call_info }
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,14 +324,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We don't refund anything for transactions that we don't support.
|
// We don't refund anything for transactions that we don't support.
|
||||||
let (relayer, call_type) = match pre {
|
let (relayer, call_info) = match pre {
|
||||||
Some(Some(pre)) => (pre.relayer, pre.call_type),
|
Some(Some(pre)) => (pre.relayer, pre.call_info),
|
||||||
_ => return Ok(()),
|
_ => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// check if relay chain state has been updated
|
// check if relay chain state has been updated
|
||||||
if let CallType::AllFinalityAndDelivery(relay_block_number, _, _) = call_type {
|
if let Some(relay_block_number) = call_info.submit_finality_proof_info() {
|
||||||
if !SubmitFinalityProofHelper::<R, GI>::was_successful(relay_block_number) {
|
if !SubmitFinalityProofHelper::<Runtime, Runtime::BridgesGrandpaPalletInstance>::was_successful(relay_block_number) {
|
||||||
// we only refund relayer if all calls have updated chain state
|
// we only refund relayer if all calls have updated chain state
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
@@ -291,44 +345,44 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if parachain state has been updated
|
// check if parachain state has been updated
|
||||||
match call_type {
|
if let Some(para_proof_info) = call_info.submit_parachain_heads_info() {
|
||||||
CallType::AllFinalityAndDelivery(_, parachain_heads_info, _) |
|
if !SubmitParachainHeadsHelper::<Runtime, Para::Instance>::was_successful(
|
||||||
CallType::ParachainFinalityAndDelivery(parachain_heads_info, _) => {
|
para_proof_info,
|
||||||
if !SubmitParachainHeadsHelper::<R, PI>::was_successful(¶chain_heads_info) {
|
) {
|
||||||
// we only refund relayer if all calls have updated chain state
|
// we only refund relayer if all calls have updated chain state
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that
|
// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that
|
||||||
// it contained. If this happens, we consider the transaction "helpful" and refund it.
|
// it contained. If this happens, we consider the transaction "helpful" and refund it.
|
||||||
let messages_proof_info = call_type.receive_messages_proof_info();
|
let msgs_proof_info = call_info.receive_messages_proof_info();
|
||||||
if !ReceiveMessagesProofHelper::<R, MI>::was_partially_successful(&messages_proof_info) {
|
if !ReceiveMessagesProofHelper::<Runtime, Msgs::Instance>::was_partially_successful(
|
||||||
|
msgs_proof_info,
|
||||||
|
) {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// regarding the tip - refund that happens here (at this side of the bridge) isn't the whole
|
// regarding the tip - refund that happens here (at this side of the bridge) isn't the whole
|
||||||
// relayer compensation. He'll receive some amount at the other side of the bridge. It shall
|
// relayer compensation. He'll receive some amount at the other side of the bridge. It shall
|
||||||
// (in theory) cover the tip here. Otherwise, if we'll be compensating tip here, some
|
// (in theory) cover the tip there. Otherwise, if we'll be compensating tip here, some
|
||||||
// malicious relayer may use huge tips, effectively depleting account that pay rewards. The
|
// malicious relayer may use huge tips, effectively depleting account that pay rewards. The
|
||||||
// cost of this attack is nothing. Hence we use zero as tip here.
|
// cost of this attack is nothing. Hence we use zero as tip here.
|
||||||
let tip = Zero::zero();
|
let tip = Zero::zero();
|
||||||
|
|
||||||
// compute the relayer reward
|
// compute the relayer refund
|
||||||
let reward = FEE::compute_fee(info, post_info, len, tip);
|
let refund = Refund::compute_refund(info, post_info, len, tip);
|
||||||
|
// finally - register refund in relayers pallet
|
||||||
// finally - register reward in relayers pallet
|
RelayersPallet::<Runtime>::register_relayer_reward(Msgs::Id::get(), &relayer, refund);
|
||||||
RelayersPallet::<R>::register_relayer_reward(LID::get(), &relayer, reward);
|
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "runtime::bridge",
|
target: "runtime::bridge",
|
||||||
"RefundRelayerForMessagesFromParachain from parachain {} via {:?} has registered {:?} reward: {:?}",
|
"{} from parachain {} via {:?} has registered reward: {:?} for {:?}",
|
||||||
PID::get(),
|
Self::IDENTIFIER,
|
||||||
LID::get(),
|
Para::Id::get(),
|
||||||
|
Msgs::Id::get(),
|
||||||
|
refund,
|
||||||
relayer,
|
relayer,
|
||||||
reward,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -353,18 +407,17 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
pub TestParachain: u32 = 1000;
|
TestParachain: u32 = 1000;
|
||||||
pub TestLaneId: LaneId = TEST_LANE_ID;
|
pub TestLaneId: LaneId = TEST_LANE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestExtension = RefundRelayerForMessagesFromParachain<
|
bp_runtime::generate_static_str_provider!(TestExtension);
|
||||||
TestRuntime,
|
type TestExtension = RefundBridgedParachainMessages<
|
||||||
(),
|
|
||||||
(),
|
|
||||||
(),
|
|
||||||
TestParachain,
|
|
||||||
TestLaneId,
|
|
||||||
TestRuntime,
|
TestRuntime,
|
||||||
|
RefundableParachain<(), TestParachain>,
|
||||||
|
RefundableMessagesLane<(), TestLaneId>,
|
||||||
|
ActualFeeRefund<TestRuntime>,
|
||||||
|
StrTestExtension,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
fn relayer_account_at_this_chain() -> ThisChainAccountId {
|
fn relayer_account_at_this_chain() -> ThisChainAccountId {
|
||||||
@@ -470,7 +523,7 @@ mod tests {
|
|||||||
fn all_finality_pre_dispatch_data() -> PreDispatchData<ThisChainAccountId> {
|
fn all_finality_pre_dispatch_data() -> PreDispatchData<ThisChainAccountId> {
|
||||||
PreDispatchData {
|
PreDispatchData {
|
||||||
relayer: relayer_account_at_this_chain(),
|
relayer: relayer_account_at_this_chain(),
|
||||||
call_type: CallType::AllFinalityAndDelivery(
|
call_info: CallInfo::AllFinalityAndDelivery(
|
||||||
200,
|
200,
|
||||||
SubmitParachainHeadsInfo {
|
SubmitParachainHeadsInfo {
|
||||||
at_relay_block_number: 200,
|
at_relay_block_number: 200,
|
||||||
@@ -489,7 +542,7 @@ mod tests {
|
|||||||
fn parachain_finality_pre_dispatch_data() -> PreDispatchData<ThisChainAccountId> {
|
fn parachain_finality_pre_dispatch_data() -> PreDispatchData<ThisChainAccountId> {
|
||||||
PreDispatchData {
|
PreDispatchData {
|
||||||
relayer: relayer_account_at_this_chain(),
|
relayer: relayer_account_at_this_chain(),
|
||||||
call_type: CallType::ParachainFinalityAndDelivery(
|
call_info: CallInfo::ParachainFinalityAndDelivery(
|
||||||
SubmitParachainHeadsInfo {
|
SubmitParachainHeadsInfo {
|
||||||
at_relay_block_number: 200,
|
at_relay_block_number: 200,
|
||||||
para_id: ParaId(TestParachain::get()),
|
para_id: ParaId(TestParachain::get()),
|
||||||
@@ -507,7 +560,7 @@ mod tests {
|
|||||||
fn delivery_pre_dispatch_data() -> PreDispatchData<ThisChainAccountId> {
|
fn delivery_pre_dispatch_data() -> PreDispatchData<ThisChainAccountId> {
|
||||||
PreDispatchData {
|
PreDispatchData {
|
||||||
relayer: relayer_account_at_this_chain(),
|
relayer: relayer_account_at_this_chain(),
|
||||||
call_type: CallType::Delivery(ReceiveMessagesProofInfo {
|
call_info: CallInfo::Delivery(ReceiveMessagesProofInfo {
|
||||||
lane_id: TEST_LANE_ID,
|
lane_id: TEST_LANE_ID,
|
||||||
best_proof_nonce: 200,
|
best_proof_nonce: 200,
|
||||||
best_stored_nonce: 100,
|
best_stored_nonce: 100,
|
||||||
@@ -520,14 +573,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_validate(call: RuntimeCall) -> TransactionValidity {
|
fn run_validate(call: RuntimeCall) -> TransactionValidity {
|
||||||
let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData);
|
let extension: TestExtension = RefundBridgedParachainMessages(PhantomData);
|
||||||
extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
|
extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_pre_dispatch(
|
fn run_pre_dispatch(
|
||||||
call: RuntimeCall,
|
call: RuntimeCall,
|
||||||
) -> Result<Option<PreDispatchData<ThisChainAccountId>>, TransactionValidityError> {
|
) -> Result<Option<PreDispatchData<ThisChainAccountId>>, TransactionValidityError> {
|
||||||
let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData);
|
let extension: TestExtension = RefundBridgedParachainMessages(PhantomData);
|
||||||
extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
|
extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,11 @@
|
|||||||
use crate::{Config, Pallet, RelayBlockNumber};
|
use crate::{Config, Pallet, RelayBlockNumber};
|
||||||
use bp_parachains::BestParaHeadHash;
|
use bp_parachains::BestParaHeadHash;
|
||||||
use bp_polkadot_core::parachains::{ParaHash, ParaId};
|
use bp_polkadot_core::parachains::{ParaHash, ParaId};
|
||||||
use frame_support::{dispatch::CallableCallFor, traits::IsSubType};
|
use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug};
|
||||||
use sp_runtime::{
|
use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction};
|
||||||
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
|
|
||||||
RuntimeDebug,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Info about a `SubmitParachainHeads` call which tries to update a single parachain.
|
/// Info about a `SubmitParachainHeads` call which tries to update a single parachain.
|
||||||
#[derive(Copy, Clone, PartialEq, RuntimeDebug)]
|
#[derive(PartialEq, RuntimeDebug)]
|
||||||
pub struct SubmitParachainHeadsInfo {
|
pub struct SubmitParachainHeadsInfo {
|
||||||
pub at_relay_block_number: RelayBlockNumber,
|
pub at_relay_block_number: RelayBlockNumber,
|
||||||
pub para_id: ParaId,
|
pub para_id: ParaId,
|
||||||
|
|||||||
@@ -507,6 +507,24 @@ impl WeightExtraOps for Weight {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait that provides a static `str`.
|
||||||
|
pub trait StaticStrProvider {
|
||||||
|
const STR: &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! generate_static_str_provider {
|
||||||
|
($str:expr) => {
|
||||||
|
$crate::paste::item! {
|
||||||
|
pub struct [<Str $str>];
|
||||||
|
|
||||||
|
impl $crate::StaticStrProvider for [<Str $str>] {
|
||||||
|
const STR: &'static str = stringify!($str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -531,4 +549,10 @@ mod tests {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generate_static_str_provider_works() {
|
||||||
|
generate_static_str_provider!(Test);
|
||||||
|
assert_eq!(StrTest::STR, "Test");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl ChainWithTransactions for Millau {
|
|||||||
frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
|
frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
|
||||||
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(unsigned.tip),
|
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(unsigned.tip),
|
||||||
millau_runtime::BridgeRejectObsoleteHeadersAndMessages,
|
millau_runtime::BridgeRejectObsoleteHeadersAndMessages,
|
||||||
millau_runtime::BridgeRefundRialtoParachainRelayers::default(),
|
millau_runtime::BridgeRefundRialtoParachainMessages::default(),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(),
|
(),
|
||||||
|
|||||||
Reference in New Issue
Block a user