Skip to content

Commit 3a20fd9

Browse files
authored
Backport xcm bridging extensions to the bridge repo (paritytech#1813)
* Backport xcm bridging extensions to the bridge repo * Fixes * Fixes
1 parent e7caa5d commit 3a20fd9

File tree

3 files changed

+189
-5
lines changed

3 files changed

+189
-5
lines changed

bridges/bin/runtime-common/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub mod messages;
2828
pub mod messages_api;
2929
pub mod messages_benchmarking;
3030
pub mod messages_call_ext;
31+
pub mod messages_xcm_extension;
3132
pub mod parachains_benchmarking;
3233
pub mod refund_relayer_extension;
3334

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

41+
const LOG_TARGET_BRIDGE_DISPATCH: &str = "runtime::bridge-dispatch";
42+
4043
/// A duplication of the `FilterCall` trait.
4144
///
4245
/// We need this trait in order to be able to implement it for the messages pallet,

bridges/bin/runtime-common/src/messages.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ pub mod target {
497497
let weight = XcmWeigher::weight(&mut payload.xcm.1);
498498
let weight = weight.unwrap_or_else(|e| {
499499
log::debug!(
500-
target: "runtime::bridge-dispatch",
500+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
501501
"Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}",
502502
message.key.lane_id,
503503
message.key.nonce,
@@ -525,7 +525,7 @@ pub mod target {
525525
let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } =
526526
message.data.payload?;
527527
log::trace!(
528-
target: "runtime::bridge-dispatch",
528+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
529529
"Going to execute message {:?} (weight limit: {:?}): {:?} {:?}",
530530
message_id,
531531
weight_limit,
@@ -551,7 +551,7 @@ pub mod target {
551551
match xcm_outcome {
552552
Ok(outcome) => {
553553
log::trace!(
554-
target: "runtime::bridge-dispatch",
554+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
555555
"Incoming message {:?} dispatched with result: {:?}",
556556
message_id,
557557
outcome,
@@ -560,7 +560,7 @@ pub mod target {
560560
Ok(_weight) => (),
561561
Err(e) => {
562562
log::error!(
563-
target: "runtime::bridge-dispatch",
563+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
564564
"Incoming message {:?} was not dispatched, error: {:?}",
565565
message_id,
566566
e,
@@ -570,7 +570,7 @@ pub mod target {
570570
},
571571
Err(e) => {
572572
log::error!(
573-
target: "runtime::bridge-dispatch",
573+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
574574
"Incoming message {:?} was not dispatched, codec error: {:?}",
575575
message_id,
576576
e,
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// Copyright 2023 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+
//! Module provides utilities for easier XCM handling, e.g:
18+
//! [`XcmExecutor`] -> [`MessageSender`] -> <outbound message queue>
19+
//! |
20+
//! <relayer>
21+
//! |
22+
//! [`XcmRouter`] <- [`MessageDispatch`] <- <inbound message queue>
23+
24+
use bp_messages::{
25+
source_chain::MessagesBridge,
26+
target_chain::{DispatchMessage, MessageDispatch},
27+
LaneId,
28+
};
29+
use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain};
30+
use codec::{Decode, Encode};
31+
use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound};
32+
use scale_info::TypeInfo;
33+
use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError};
34+
35+
/// Plain "XCM" payload, which we transfer through bridge
36+
pub type XcmAsPlainPayload = sp_std::prelude::Vec<u8>;
37+
38+
/// Message dispatch result type for single message
39+
#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
40+
pub enum XcmBlobMessageDispatchResult {
41+
InvalidPayload,
42+
Dispatched,
43+
NotDispatched(#[codec(skip)] &'static str),
44+
}
45+
46+
/// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages
47+
pub struct XcmBlobMessageDispatch<
48+
SourceBridgeHubChain,
49+
TargetBridgeHubChain,
50+
DispatchBlob,
51+
DispatchBlobWeigher,
52+
> {
53+
_marker: sp_std::marker::PhantomData<(
54+
SourceBridgeHubChain,
55+
TargetBridgeHubChain,
56+
DispatchBlob,
57+
DispatchBlobWeigher,
58+
)>,
59+
}
60+
61+
impl<
62+
SourceBridgeHubChain: Chain,
63+
TargetBridgeHubChain: Chain,
64+
BlobDispatcher: DispatchBlob,
65+
DispatchBlobWeigher: Get<Weight>,
66+
> MessageDispatch<AccountIdOf<SourceBridgeHubChain>>
67+
for XcmBlobMessageDispatch<
68+
SourceBridgeHubChain,
69+
TargetBridgeHubChain,
70+
BlobDispatcher,
71+
DispatchBlobWeigher,
72+
>
73+
{
74+
type DispatchPayload = XcmAsPlainPayload;
75+
type DispatchLevelResult = XcmBlobMessageDispatchResult;
76+
77+
fn dispatch_weight(_message: &mut DispatchMessage<Self::DispatchPayload>) -> Weight {
78+
DispatchBlobWeigher::get()
79+
}
80+
81+
fn dispatch(
82+
_relayer_account: &AccountIdOf<SourceBridgeHubChain>,
83+
message: DispatchMessage<Self::DispatchPayload>,
84+
) -> MessageDispatchResult<Self::DispatchLevelResult> {
85+
let payload = match message.data.payload {
86+
Ok(payload) => payload,
87+
Err(e) => {
88+
log::error!(
89+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
90+
"[XcmBlobMessageDispatch] payload error: {:?} - message_nonce: {:?}",
91+
e,
92+
message.key.nonce
93+
);
94+
return MessageDispatchResult {
95+
// TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629
96+
unspent_weight: Weight::zero(),
97+
dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload,
98+
}
99+
},
100+
};
101+
let dispatch_level_result = match BlobDispatcher::dispatch_blob(payload) {
102+
Ok(_) => {
103+
log::debug!(
104+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
105+
"[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob was ok - message_nonce: {:?}",
106+
message.key.nonce
107+
);
108+
XcmBlobMessageDispatchResult::Dispatched
109+
},
110+
Err(e) => {
111+
let e = match e {
112+
DispatchBlobError::Unbridgable => "DispatchBlobError::Unbridgable",
113+
DispatchBlobError::InvalidEncoding => "DispatchBlobError::InvalidEncoding",
114+
DispatchBlobError::UnsupportedLocationVersion =>
115+
"DispatchBlobError::UnsupportedLocationVersion",
116+
DispatchBlobError::UnsupportedXcmVersion =>
117+
"DispatchBlobError::UnsupportedXcmVersion",
118+
DispatchBlobError::RoutingError => "DispatchBlobError::RoutingError",
119+
DispatchBlobError::NonUniversalDestination =>
120+
"DispatchBlobError::NonUniversalDestination",
121+
DispatchBlobError::WrongGlobal => "DispatchBlobError::WrongGlobal",
122+
};
123+
log::error!(
124+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
125+
"[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}",
126+
e, message.key.nonce
127+
);
128+
XcmBlobMessageDispatchResult::NotDispatched(e)
129+
},
130+
};
131+
MessageDispatchResult {
132+
// TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629
133+
unspent_weight: Weight::zero(),
134+
dispatch_level_result,
135+
}
136+
}
137+
}
138+
139+
/// [`XcmBlobHauler`] is responsible for sending messages to the bridge "point-to-point link" from
140+
/// one side, where on the other it can be dispatched by [`XcmBlobMessageDispatch`].
141+
pub trait XcmBlobHauler {
142+
/// Runtime message sender adapter.
143+
type MessageSender: MessagesBridge<Self::MessageSenderOrigin, XcmAsPlainPayload>;
144+
145+
/// Runtime message sender origin, which is used by [`MessageSender`].
146+
type MessageSenderOrigin;
147+
/// Our location within the Consensus Universe.
148+
fn message_sender_origin() -> Self::MessageSenderOrigin;
149+
150+
/// Return message lane (as "point-to-point link") used to deliver XCM messages.
151+
fn xcm_lane() -> LaneId;
152+
}
153+
154+
/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`MessageSender`] and makes sure that
155+
/// XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed.
156+
pub struct XcmBlobHaulerAdapter<XcmBlobHauler>(sp_std::marker::PhantomData<XcmBlobHauler>);
157+
impl<HaulerOrigin, H: XcmBlobHauler<MessageSenderOrigin = HaulerOrigin>> HaulBlob
158+
for XcmBlobHaulerAdapter<H>
159+
{
160+
fn haul_blob(blob: sp_std::prelude::Vec<u8>) -> Result<(), HaulBlobError> {
161+
let lane = H::xcm_lane();
162+
let result = H::MessageSender::send_message(H::message_sender_origin(), lane, blob);
163+
let result = result
164+
.map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256));
165+
match &result {
166+
Ok(result) => log::info!(
167+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
168+
"haul_blob result - ok: {:?} on lane: {:?}",
169+
result,
170+
lane
171+
),
172+
Err(error) => log::error!(
173+
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
174+
"haul_blob result - error: {:?} on lane: {:?}",
175+
error,
176+
lane
177+
),
178+
};
179+
result.map(|_| ()).map_err(|_| HaulBlobError::Transport("MessageSenderError"))
180+
}
181+
}

0 commit comments

Comments
 (0)