Skip to content
This repository has been archived by the owner on Feb 29, 2024. It is now read-only.

Commit

Permalink
Copy & Paste to master branch
Browse files Browse the repository at this point in the history
  • Loading branch information
boundless-forest committed Jun 13, 2022
1 parent 6ac478b commit 7bb63fc
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 89 deletions.
69 changes: 0 additions & 69 deletions bin/runtime-common/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,75 +548,6 @@ pub mod target {
}
}

/// Dispatching Bridged -> This chain messages.
#[derive(RuntimeDebug, Clone, Copy)]
pub struct FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance> {
_marker: PhantomData<(B, ThisRuntime, ThisCurrency, ThisDispatchInstance)>,
}

impl<B: MessageBridge, ThisRuntime, ThisCurrency, ThisDispatchInstance>
MessageDispatch<AccountIdOf<ThisChain<B>>, BalanceOf<BridgedChain<B>>>
for FromBridgedChainMessageDispatch<B, ThisRuntime, ThisCurrency, ThisDispatchInstance>
where
BalanceOf<ThisChain<B>>: Saturating + FixedPointOperand,
ThisDispatchInstance: 'static,
ThisRuntime: pallet_bridge_dispatch::Config<
ThisDispatchInstance,
BridgeMessageId = (LaneId, MessageNonce),
> + pallet_transaction_payment::Config,
<ThisRuntime as pallet_transaction_payment::Config>::OnChargeTransaction:
pallet_transaction_payment::OnChargeTransaction<
ThisRuntime,
Balance = BalanceOf<ThisChain<B>>,
>,
ThisCurrency: Currency<AccountIdOf<ThisChain<B>>, Balance = BalanceOf<ThisChain<B>>>,
pallet_bridge_dispatch::Pallet<ThisRuntime, ThisDispatchInstance>:
bp_message_dispatch::MessageDispatch<
AccountIdOf<ThisChain<B>>,
(LaneId, MessageNonce),
Message = FromBridgedChainMessagePayload<B>,
>,
{
type DispatchPayload = FromBridgedChainMessagePayload<B>;

fn dispatch_weight(
message: &DispatchMessage<Self::DispatchPayload, BalanceOf<BridgedChain<B>>>,
) -> frame_support::weights::Weight {
message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0)
}

fn dispatch(
relayer_account: &AccountIdOf<ThisChain<B>>,
message: DispatchMessage<Self::DispatchPayload, BalanceOf<BridgedChain<B>>>,
) -> MessageDispatchResult {
let message_id = (message.key.lane_id, message.key.nonce);
pallet_bridge_dispatch::Pallet::<ThisRuntime, ThisDispatchInstance>::dispatch(
B::BRIDGED_CHAIN_ID,
B::THIS_CHAIN_ID,
message_id,
message.data.payload.map_err(drop),
|dispatch_origin, dispatch_weight| {
let unadjusted_weight_fee = ThisRuntime::WeightToFee::calc(&dispatch_weight);
let fee_multiplier =
pallet_transaction_payment::Pallet::<ThisRuntime>::next_fee_multiplier();
let adjusted_weight_fee =
fee_multiplier.saturating_mul_int(unadjusted_weight_fee);
if !adjusted_weight_fee.is_zero() {
ThisCurrency::transfer(
dispatch_origin,
relayer_account,
adjusted_weight_fee,
ExistenceRequirement::AllowDeath,
)
.map_err(drop)
} else {
Ok(())
}
},
)
}
}

/// Return maximal dispatch weight of the message we're able to receive.
pub fn maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight {
maximal_extrinsic_weight / 2
Expand Down
57 changes: 39 additions & 18 deletions modules/dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
// Generated by `decl_event!`
#![allow(clippy::unused_unit)]

use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion};
use bp_message_dispatch::{
CallFilter, CallOrigin, IntoDispatchOrigin, MessageDispatch, MessagePayload, SpecVersion,
};
use bp_runtime::{
derive_account_id,
messages::{DispatchFeePayment, MessageDispatchResult},
Expand All @@ -35,7 +37,7 @@ use codec::Encode;
use frame_support::{
dispatch::Dispatchable,
ensure,
traits::{Contains, Get},
traits::Get,
weights::{extract_actual_weight, GetDispatchInfo},
};
use frame_system::RawOrigin;
Expand Down Expand Up @@ -81,7 +83,7 @@ pub mod pallet {
///
/// The pallet will filter all incoming calls right before they're dispatched. If this
/// filter rejects the call, special event (`Event::MessageCallRejected`) is emitted.
type CallFilter: Contains<<Self as Config<I>>::Call>;
type CallFilter: CallFilter<Self::Origin, <Self as Config<I>>::Call>;
/// The type that is used to wrap the `Self::Call` when it is moved over bridge.
///
/// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure
Expand All @@ -93,6 +95,12 @@ pub mod pallet {
///
/// Used when deriving target chain AccountIds from source chain AccountIds.
type AccountIdConverter: sp_runtime::traits::Convert<sp_core::hash::H256, Self::AccountId>;
/// The type is used to customize the dispatch call origin.
type IntoDispatchOrigin: IntoDispatchOrigin<
Self::AccountId,
<Self as Config<I>>::Call,
Self::Origin,
>;
}

type BridgeMessageIdOf<T, I> = <T as Config<I>>::BridgeMessageId;
Expand Down Expand Up @@ -138,7 +146,9 @@ pub mod pallet {
}
}

impl<T: Config<I>, I: 'static> MessageDispatch<T::AccountId, T::BridgeMessageId> for Pallet<T, I> {
impl<T: Config<I>, I: 'static>
MessageDispatch<T::Origin, T::BridgeMessageId, <T as pallet::Config<I>>::Call> for Pallet<T, I>
{
type Message = MessagePayload<
T::SourceChainAccountId,
T::TargetChainAccountPublic,
Expand All @@ -150,7 +160,7 @@ impl<T: Config<I>, I: 'static> MessageDispatch<T::AccountId, T::BridgeMessageId>
message.weight
}

fn dispatch<P: FnOnce(&T::AccountId, bp_message_dispatch::Weight) -> Result<(), ()>>(
fn dispatch<P: FnOnce(&T::Origin, &<T as pallet::Config<I>>::Call) -> Result<(), ()>>(
source_chain: ChainId,
target_chain: ChainId,
id: T::BridgeMessageId,
Expand Down Expand Up @@ -260,8 +270,11 @@ impl<T: Config<I>, I: 'static> MessageDispatch<T::AccountId, T::BridgeMessageId>
},
};

// generate dispatch origin from origin account
let origin = T::IntoDispatchOrigin::into_dispatch_origin(&origin_account, &call);

// filter the call
if !T::CallFilter::contains(&call) {
if !T::CallFilter::contains(&origin, &call) {
log::trace!(
target: "runtime::bridge-dispatch",
"Message {:?}/{:?}: the call ({:?}) is rejected by filter",
Expand Down Expand Up @@ -299,9 +312,7 @@ impl<T: Config<I>, I: 'static> MessageDispatch<T::AccountId, T::BridgeMessageId>
// pay dispatch fee right before dispatch
let pay_dispatch_fee_at_target_chain =
message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain;
if pay_dispatch_fee_at_target_chain
&& pay_dispatch_fee(&origin_account, message.weight).is_err()
{
if pay_dispatch_fee_at_target_chain && pay_dispatch_fee(&origin, &call).is_err() {
log::trace!(
target: "runtime::bridge-dispatch",
"Failed to pay dispatch fee for dispatching message {:?}/{:?} with weight {}",
Expand All @@ -319,9 +330,6 @@ impl<T: Config<I>, I: 'static> MessageDispatch<T::AccountId, T::BridgeMessageId>
}
dispatch_result.dispatch_fee_paid_during_dispatch = pay_dispatch_fee_at_target_chain;

// finally dispatch message
let origin = RawOrigin::Signed(origin_account).into();

log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call);
let result = call.dispatch(origin);
let actual_call_weight = extract_actual_weight(&result, &dispatch_info);
Expand Down Expand Up @@ -529,6 +537,7 @@ mod tests {
type CallFilter = TestCallFilter;
type EncodedCall = EncodedCall;
type Event = Event;
type IntoDispatchOrigin = TestIntoDispatchOrigin;
type SourceChainAccountId = AccountId;
type TargetChainAccountPublic = TestAccountPublic;
type TargetChainSignature = TestSignature;
Expand All @@ -545,12 +554,20 @@ mod tests {

pub struct TestCallFilter;

impl Contains<Call> for TestCallFilter {
fn contains(call: &Call) -> bool {
impl CallFilter<Origin, Call> for TestCallFilter {
fn contains(_origin: &Origin, call: &Call) -> bool {
!matches!(*call, Call::System(frame_system::Call::fill_block { .. }))
}
}

pub struct TestIntoDispatchOrigin;

impl IntoDispatchOrigin<AccountId, Call, Origin> for TestIntoDispatchOrigin {
fn into_dispatch_origin(id: &AccountId, _call: &Call) -> Origin {
frame_system::RawOrigin::Signed(*id).into()
}
}

const TEST_SPEC_VERSION: SpecVersion = 0;
const TEST_WEIGHT: Weight = 1_000_000_000;

Expand All @@ -563,8 +580,9 @@ mod tests {
origin: CallOrigin<AccountId, TestAccountPublic, TestSignature>,
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<
AccountId,
<TestRuntime as frame_system::Config>::Origin,
<TestRuntime as Config>::BridgeMessageId,
<TestRuntime as Config>::Call,
>>::Message {
MessagePayload {
spec_version: TEST_SPEC_VERSION,
Expand All @@ -578,17 +596,19 @@ mod tests {
fn prepare_root_message(
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<
AccountId,
<TestRuntime as frame_system::Config>::Origin,
<TestRuntime as Config>::BridgeMessageId,
<TestRuntime as Config>::Call,
>>::Message {
prepare_message(CallOrigin::SourceRoot, call)
}

fn prepare_target_message(
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<
AccountId,
<TestRuntime as frame_system::Config>::Origin,
<TestRuntime as Config>::BridgeMessageId,
<TestRuntime as Config>::Call,
>>::Message {
let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1));
prepare_message(origin, call)
Expand All @@ -597,8 +617,9 @@ mod tests {
fn prepare_source_message(
call: Call,
) -> <Pallet<TestRuntime> as MessageDispatch<
AccountId,
<TestRuntime as frame_system::Config>::Origin,
<TestRuntime as Config>::BridgeMessageId,
<TestRuntime as Config>::Call,
>>::Message {
let origin = CallOrigin::SourceAccount(1);
prepare_message(origin, call)
Expand Down
19 changes: 17 additions & 2 deletions primitives/message-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub type Weight = u64;
pub type SpecVersion = u32;

/// A generic trait to dispatch arbitrary messages delivered over the bridge.
pub trait MessageDispatch<AccountId, BridgeMessageId> {
pub trait MessageDispatch<Origin, BridgeMessageId, Call> {
/// A type of the message to be dispatched.
type Message: codec::Decode;

Expand All @@ -58,7 +58,7 @@ pub trait MessageDispatch<AccountId, BridgeMessageId> {
/// the whole message).
///
/// Returns unspent dispatch weight.
fn dispatch<P: FnOnce(&AccountId, Weight) -> Result<(), ()>>(
fn dispatch<P: FnOnce(&Origin, &Call) -> Result<(), ()>>(
source_chain: ChainId,
target_chain: ChainId,
id: BridgeMessageId,
Expand Down Expand Up @@ -140,3 +140,18 @@ impl<SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature> Size
self.call.len() as _
}
}

/// Customize the dispatch origin before call dispatch.
pub trait IntoDispatchOrigin<AccountId, Call, Origin> {
/// Generate the dispatch origin for the given call.
///
/// Normally, the dispatch origin is one kind of frame_system::RawOrigin, however, sometimes
/// it is useful for a dispatch call with a custom origin.
fn into_dispatch_origin(id: &AccountId, call: &Call) -> Origin;
}

/// A generic trait to filter calls that are allowed to be dispatched.
pub trait CallFilter<Origin, Call> {
/// Filter the call, you might need origin to in the filter. return false, if not allowed.
fn contains(origin: &Origin, call: &Call) -> bool;
}

0 comments on commit 7bb63fc

Please sign in to comment.