From 43a7b2e47790b8b6ff426d5196144807aa9edb63 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 23 Jan 2023 16:56:37 +0100 Subject: [PATCH 1/3] Backport xcm bridging extensions to the bridge repo --- bin/runtime-common/src/lib.rs | 3 + bin/runtime-common/src/messages.rs | 10 +- .../src/messages_xcm_extension.rs | 170 ++++++++++++++++++ 3 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 bin/runtime-common/src/messages_xcm_extension.rs diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 9f31450bd28..2e92e00d5a2 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -26,6 +26,7 @@ pub mod messages; pub mod messages_api; pub mod messages_benchmarking; pub mod messages_extension; +pub mod messages_xcm_extension; pub mod parachains_benchmarking; pub mod refund_relayer_extension; @@ -35,6 +36,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, diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 8c97198393d..a00a362eeba 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -476,7 +476,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, @@ -504,7 +504,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, @@ -530,7 +530,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, @@ -539,7 +539,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, @@ -549,7 +549,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, diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs new file mode 100644 index 00000000000..6e4ce5958ac --- /dev/null +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -0,0 +1,170 @@ +// Copyright 2022 Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +//! Module provides utilities for easier XCM handling, e.g: +//! [`XcmExecutor`] -> [`MessageSender`] -> +//! | +//! +//! | +//! [`XcmRouter`] <- [`MessageDispatch`] <- + +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, 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; + +/// 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 { + _marker: + sp_std::marker::PhantomData<(SourceBridgeHubChain, TargetBridgeHubChain, DispatchBlob)>, +} + +impl + MessageDispatch> + for XcmBlobMessageDispatch +{ + type DispatchPayload = XcmAsPlainPayload; + type DispatchLevelResult = XcmBlobMessageDispatchResult; + + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + log::error!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "[XcmBlobMessageDispatch] TODO: change here to XCMv3 dispatch_weight with XcmExecutor - message: ?...?", + ); + // TODO:check-parameter - setup weight? + Weight::zero() + } + + fn dispatch( + _relayer_account: &AccountIdOf, + message: DispatchMessage, + ) -> MessageDispatchResult { + 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? + 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? + 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; + + /// 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(sp_std::marker::PhantomData); +impl> HaulBlob + for XcmBlobHaulerAdapter +{ + fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { + let lane = H::xcm_lane(); + let result = H::MessageSender::send_message(H::message_sender_origin(), lane, blob); + let result = result.map(|artifacts| { + let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); + hash + }); + 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")) + } +} From cee886f7f8c2d684aa71280ea80be6d077505c58 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 13 Mar 2023 14:12:24 +0100 Subject: [PATCH 2/3] Fixes --- bin/runtime-common/src/lib.rs | 2 +- .../src/messages_xcm_extension.rs | 53 ++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 1094363ac5e..ed486c04abc 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -27,8 +27,8 @@ use xcm::v3::NetworkId; pub mod messages; pub mod messages_api; pub mod messages_benchmarking; -pub mod messages_xcm_extension; pub mod messages_call_ext; +pub mod messages_xcm_extension; pub mod parachains_benchmarking; pub mod refund_relayer_extension; diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 6e4ce5958ac..1ab3484efbe 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -1,18 +1,18 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. -// This file is part of Cumulus. +// Copyright 2023 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. -// Cumulus is free software: you can redistribute it and/or modify +// 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. -// Cumulus is distributed in the hope that it will be useful, +// 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 Cumulus. If not, see . +// along with Parity Bridges Common. If not, see . //! Module provides utilities for easier XCM handling, e.g: //! [`XcmExecutor`] -> [`MessageSender`] -> @@ -28,7 +28,7 @@ use bp_messages::{ }; use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; use codec::{Decode, Encode}; -use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; +use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound}; use scale_info::TypeInfo; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; @@ -44,25 +44,38 @@ pub enum XcmBlobMessageDispatchResult { } /// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages -pub struct XcmBlobMessageDispatch { - _marker: - sp_std::marker::PhantomData<(SourceBridgeHubChain, TargetBridgeHubChain, DispatchBlob)>, +pub struct XcmBlobMessageDispatch< + SourceBridgeHubChain, + TargetBridgeHubChain, + DispatchBlob, + DispatchBlobWeigher, +> { + _marker: sp_std::marker::PhantomData<( + SourceBridgeHubChain, + TargetBridgeHubChain, + DispatchBlob, + DispatchBlobWeigher, + )>, } -impl - MessageDispatch> - for XcmBlobMessageDispatch +impl< + SourceBridgeHubChain: Chain, + TargetBridgeHubChain: Chain, + BlobDispatcher: DispatchBlob, + DispatchBlobWeigher: Get, + > MessageDispatch> + for XcmBlobMessageDispatch< + SourceBridgeHubChain, + TargetBridgeHubChain, + BlobDispatcher, + DispatchBlobWeigher, + > { type DispatchPayload = XcmAsPlainPayload; type DispatchLevelResult = XcmBlobMessageDispatchResult; fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "[XcmBlobMessageDispatch] TODO: change here to XCMv3 dispatch_weight with XcmExecutor - message: ?...?", - ); - // TODO:check-parameter - setup weight? - Weight::zero() + DispatchBlobWeigher::get() } fn dispatch( @@ -79,7 +92,7 @@ impl Date: Mon, 13 Mar 2023 14:49:04 +0100 Subject: [PATCH 3/3] Fixes --- bin/runtime-common/src/messages_xcm_extension.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 1ab3484efbe..7163d8a5357 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -16,9 +16,9 @@ //! Module provides utilities for easier XCM handling, e.g: //! [`XcmExecutor`] -> [`MessageSender`] -> -//! | -//! -//! | +//! | +//! +//! | //! [`XcmRouter`] <- [`MessageDispatch`] <- use bp_messages::{ @@ -32,7 +32,7 @@ use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, Part use scale_info::TypeInfo; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; -/// PLain "XCM" payload, which we transfer through bridge +/// Plain "XCM" payload, which we transfer through bridge pub type XcmAsPlainPayload = sp_std::prelude::Vec; /// Message dispatch result type for single message @@ -142,7 +142,7 @@ pub trait XcmBlobHauler { /// Runtime message sender adapter. type MessageSender: MessagesBridge; - /// Runtime message sender origin, which is used by MessageSender. + /// Runtime message sender origin, which is used by [`MessageSender`]. type MessageSenderOrigin; /// Our location within the Consensus Universe. fn message_sender_origin() -> Self::MessageSenderOrigin; @@ -160,10 +160,8 @@ impl> HaulBlo fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { let lane = H::xcm_lane(); let result = H::MessageSender::send_message(H::message_sender_origin(), lane, blob); - let result = result.map(|artifacts| { - let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); - hash - }); + 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,