Skip to content

Commit

Permalink
Backport xcm bridging extensions to the bridge repo (#1813)
Browse files Browse the repository at this point in the history
* Backport xcm bridging extensions to the bridge repo

* Fixes

* Fixes
  • Loading branch information
bkontur authored Mar 13, 2023
1 parent 88c1114 commit 7b946da
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 5 deletions.
3 changes: 3 additions & 0 deletions bin/runtime-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod messages;
pub mod messages_api;
pub mod messages_benchmarking;
pub mod messages_call_ext;
pub mod messages_xcm_extension;
pub mod parachains_benchmarking;
pub mod refund_relayer_extension;

Expand All @@ -37,6 +38,8 @@ mod mock;
#[cfg(feature = "integrity-test")]
pub mod integrity;

const LOG_TARGET_BRIDGE_DISPATCH: &str = "runtime::bridge-dispatch";

/// A duplication of the `FilterCall` trait.
///
/// We need this trait in order to be able to implement it for the messages pallet,
Expand Down
10 changes: 5 additions & 5 deletions bin/runtime-common/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ pub mod target {
let weight = XcmWeigher::weight(&mut payload.xcm.1);
let weight = weight.unwrap_or_else(|e| {
log::debug!(
target: "runtime::bridge-dispatch",
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}",
message.key.lane_id,
message.key.nonce,
Expand Down Expand Up @@ -525,7 +525,7 @@ pub mod target {
let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } =
message.data.payload?;
log::trace!(
target: "runtime::bridge-dispatch",
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"Going to execute message {:?} (weight limit: {:?}): {:?} {:?}",
message_id,
weight_limit,
Expand All @@ -551,7 +551,7 @@ pub mod target {
match xcm_outcome {
Ok(outcome) => {
log::trace!(
target: "runtime::bridge-dispatch",
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"Incoming message {:?} dispatched with result: {:?}",
message_id,
outcome,
Expand All @@ -560,7 +560,7 @@ pub mod target {
Ok(_weight) => (),
Err(e) => {
log::error!(
target: "runtime::bridge-dispatch",
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"Incoming message {:?} was not dispatched, error: {:?}",
message_id,
e,
Expand All @@ -570,7 +570,7 @@ pub mod target {
},
Err(e) => {
log::error!(
target: "runtime::bridge-dispatch",
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"Incoming message {:?} was not dispatched, codec error: {:?}",
message_id,
e,
Expand Down
181 changes: 181 additions & 0 deletions bin/runtime-common/src/messages_xcm_extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Copyright 2023 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 <http://www.gnu.org/licenses/>.

//! Module provides utilities for easier XCM handling, e.g:
//! [`XcmExecutor`] -> [`MessageSender`] -> <outbound message queue>
//! |
//! <relayer>
//! |
//! [`XcmRouter`] <- [`MessageDispatch`] <- <inbound message queue>

use bp_messages::{
source_chain::MessagesBridge,
target_chain::{DispatchMessage, MessageDispatch},
LaneId,
};
use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain};
use codec::{Decode, Encode};
use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound};
use scale_info::TypeInfo;
use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError};

/// Plain "XCM" payload, which we transfer through bridge
pub type XcmAsPlainPayload = sp_std::prelude::Vec<u8>;

/// Message dispatch result type for single message
#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
pub enum XcmBlobMessageDispatchResult {
InvalidPayload,
Dispatched,
NotDispatched(#[codec(skip)] &'static str),
}

/// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages
pub struct XcmBlobMessageDispatch<
SourceBridgeHubChain,
TargetBridgeHubChain,
DispatchBlob,
DispatchBlobWeigher,
> {
_marker: sp_std::marker::PhantomData<(
SourceBridgeHubChain,
TargetBridgeHubChain,
DispatchBlob,
DispatchBlobWeigher,
)>,
}

impl<
SourceBridgeHubChain: Chain,
TargetBridgeHubChain: Chain,
BlobDispatcher: DispatchBlob,
DispatchBlobWeigher: Get<Weight>,
> MessageDispatch<AccountIdOf<SourceBridgeHubChain>>
for XcmBlobMessageDispatch<
SourceBridgeHubChain,
TargetBridgeHubChain,
BlobDispatcher,
DispatchBlobWeigher,
>
{
type DispatchPayload = XcmAsPlainPayload;
type DispatchLevelResult = XcmBlobMessageDispatchResult;

fn dispatch_weight(_message: &mut DispatchMessage<Self::DispatchPayload>) -> Weight {
DispatchBlobWeigher::get()
}

fn dispatch(
_relayer_account: &AccountIdOf<SourceBridgeHubChain>,
message: DispatchMessage<Self::DispatchPayload>,
) -> MessageDispatchResult<Self::DispatchLevelResult> {
let payload = match message.data.payload {
Ok(payload) => payload,
Err(e) => {
log::error!(
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"[XcmBlobMessageDispatch] payload error: {:?} - message_nonce: {:?}",
e,
message.key.nonce
);
return MessageDispatchResult {
// TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629
unspent_weight: Weight::zero(),
dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload,
}
},
};
let dispatch_level_result = match BlobDispatcher::dispatch_blob(payload) {
Ok(_) => {
log::debug!(
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob was ok - message_nonce: {:?}",
message.key.nonce
);
XcmBlobMessageDispatchResult::Dispatched
},
Err(e) => {
let e = match e {
DispatchBlobError::Unbridgable => "DispatchBlobError::Unbridgable",
DispatchBlobError::InvalidEncoding => "DispatchBlobError::InvalidEncoding",
DispatchBlobError::UnsupportedLocationVersion =>
"DispatchBlobError::UnsupportedLocationVersion",
DispatchBlobError::UnsupportedXcmVersion =>
"DispatchBlobError::UnsupportedXcmVersion",
DispatchBlobError::RoutingError => "DispatchBlobError::RoutingError",
DispatchBlobError::NonUniversalDestination =>
"DispatchBlobError::NonUniversalDestination",
DispatchBlobError::WrongGlobal => "DispatchBlobError::WrongGlobal",
};
log::error!(
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}",
e, message.key.nonce
);
XcmBlobMessageDispatchResult::NotDispatched(e)
},
};
MessageDispatchResult {
// TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629
unspent_weight: Weight::zero(),
dispatch_level_result,
}
}
}

/// [`XcmBlobHauler`] is responsible for sending messages to the bridge "point-to-point link" from
/// one side, where on the other it can be dispatched by [`XcmBlobMessageDispatch`].
pub trait XcmBlobHauler {
/// Runtime message sender adapter.
type MessageSender: MessagesBridge<Self::MessageSenderOrigin, XcmAsPlainPayload>;

/// Runtime message sender origin, which is used by [`MessageSender`].
type MessageSenderOrigin;
/// Our location within the Consensus Universe.
fn message_sender_origin() -> Self::MessageSenderOrigin;

/// Return message lane (as "point-to-point link") used to deliver XCM messages.
fn xcm_lane() -> LaneId;
}

/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`MessageSender`] and makes sure that
/// XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed.
pub struct XcmBlobHaulerAdapter<XcmBlobHauler>(sp_std::marker::PhantomData<XcmBlobHauler>);
impl<HaulerOrigin, H: XcmBlobHauler<MessageSenderOrigin = HaulerOrigin>> HaulBlob
for XcmBlobHaulerAdapter<H>
{
fn haul_blob(blob: sp_std::prelude::Vec<u8>) -> Result<(), HaulBlobError> {
let lane = H::xcm_lane();
let result = H::MessageSender::send_message(H::message_sender_origin(), lane, blob);
let result = result
.map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256));
match &result {
Ok(result) => log::info!(
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"haul_blob result - ok: {:?} on lane: {:?}",
result,
lane
),
Err(error) => log::error!(
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
"haul_blob result - error: {:?} on lane: {:?}",
error,
lane
),
};
result.map(|_| ()).map_err(|_| HaulBlobError::Transport("MessageSenderError"))
}
}

0 comments on commit 7b946da

Please sign in to comment.