From a75c28d5b29b3646aedd53dacf09eafa95e57c58 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky <svyatonik@gmail.com> Date: Thu, 23 Mar 2023 10:44:53 +0300 Subject: [PATCH] Remove deprecated code from bridge-runtime-common (#1983) * removed FromBridgedChainMessageDispatch in favor of XcmBlobMessageDispatch * use HaulBlobExporter/HaulBlobExporterAdapter instead of XcmBridge/XcmBridgeAdapter * tests for sending/dispatching messages * use new schema in testnet bridges + some cleanup * clippy * spelling + added TODO * cleanup some checks * benchmarks compilation * all is XCM * updated README.md * ref issue from TODO --- bridges/README.md | 9 +- bridges/bin/millau/runtime/src/lib.rs | 8 +- .../bin/millau/runtime/src/rialto_messages.rs | 68 ++-- .../runtime/src/rialto_parachain_messages.rs | 70 ++-- bridges/bin/millau/runtime/src/xcm_config.rs | 304 +++++++++------ .../bin/rialto-parachain/runtime/Cargo.toml | 2 + .../bin/rialto-parachain/runtime/src/lib.rs | 177 ++++----- .../runtime/src/millau_messages.rs | 64 ++-- .../bin/rialto/runtime/src/millau_messages.rs | 68 ++-- bridges/bin/rialto/runtime/src/xcm_config.rs | 177 +++++---- bridges/bin/runtime-common/src/integrity.rs | 2 +- bridges/bin/runtime-common/src/messages.rs | 355 ++---------------- .../src/messages_xcm_extension.rs | 32 +- bridges/bin/runtime-common/src/mock.rs | 46 +-- bridges/primitives/runtime/src/lib.rs | 4 +- .../relays/bin-substrate/src/chains/millau.rs | 29 +- .../relays/bin-substrate/src/chains/rialto.rs | 21 +- .../src/chains/rialto_parachain.rs | 22 +- .../relays/bin-substrate/src/cli/bridge.rs | 22 -- .../bin-substrate/src/cli/encode_message.rs | 18 +- .../bin-substrate/src/cli/send_message.rs | 7 +- 21 files changed, 610 insertions(+), 895 deletions(-) diff --git a/bridges/README.md b/bridges/README.md index b5885026426..aab6007d2cd 100644 --- a/bridges/README.md +++ b/bridges/README.md @@ -215,18 +215,19 @@ In this section we'll show you how to quickly send a bridge message. The message After sending a message you will see the following logs showing a message was successfully sent: ``` -INFO bridge Sending message to Rialto. Size: 5. +INFO bridge Sending message to Rialto. Size: 11. TRACE bridge Sent transaction to Millau node: 0x5e68... ``` And at the Rialto node logs you'll something like this: ``` -... runtime::bridge-dispatch: Going to execute message ([0, 0, 0, 0], 1) (...), Trap(43)]) -... runtime::bridge-dispatch: Incoming message ([0, 0, 0, 0], 1) dispatched with result: Incomplete(2000000000, Trap(43)) +... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: 48559)/Weight(ref_time: 1215065371, proof_size: 54703). ``` -It means that the message has been delivered and successfully dispatched. +It means that the message has been delivered and dispatched. Message may be dispatched with an +error, though - the goal of our test bridge is to ensure that messages are successfully delivered +and all involved components are working. ## Full Network Docker Compose Setup diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 574b0569875..f08f5e1c749 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -1021,10 +1021,8 @@ impl_runtime_apis! { } fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - use bridge_runtime_common::messages::MessageBridge; - let lane = <Self as MessagesConfig<WithRialtoParachainMessagesInstance>>::bench_lane_id(); - let bridged_chain_id = WithRialtoParachainMessageBridge::BRIDGED_CHAIN_ID; + let bridged_chain_id = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward( relayer, RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) @@ -1054,10 +1052,8 @@ impl_runtime_apis! { } fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - use bridge_runtime_common::messages::MessageBridge; - let lane = <Self as MessagesConfig<WithRialtoMessagesInstance>>::bench_lane_id(); - let bridged_chain_id = WithRialtoMessageBridge::BRIDGED_CHAIN_ID; + let bridged_chain_id = bp_runtime::RIALTO_CHAIN_ID; pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward( relayer, RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 919fac86899..311805c9849 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -16,14 +16,18 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use crate::{RialtoGrandpaInstance, Runtime, RuntimeOrigin, WithRialtoMessagesInstance}; + +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -48,7 +52,7 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier<WithRialtoMessageBridge>; /// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload<RuntimeCall>; +pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Messages proof for Rialto -> Millau messages. pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_rialto::Hash>; @@ -58,12 +62,13 @@ pub type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof<bp_rialto::Hash>; /// Call-dispatch based message dispatch for Rialto -> Millau messages. -pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithRialtoMessageBridge, - xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>, - crate::xcm_config::XcmWeigher, - WeightCredit, ->; +pub type FromRialtoMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_millau::Millau, + bp_rialto::Rialto, + crate::xcm_config::OnMillauBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<crate::DbWeight>, + >; /// Maximal outbound payload size of Millau -> Rialto messages. pub type ToRialtoMaximalOutboundPayloadSize = @@ -74,8 +79,6 @@ pub type ToRialtoMaximalOutboundPayloadSize = pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { - const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; @@ -94,15 +97,6 @@ impl messages::UnderlyingChainProvider for Millau { impl messages::ThisChainWithMessages for Millau { type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// Rialto chain from message lane point of view. @@ -117,9 +111,29 @@ impl messages::UnderlyingChainProvider for Rialto { type Chain = bp_rialto::Rialto; } -impl messages::BridgedChainWithMessages for Rialto { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for Rialto {} + +/// Export XCM messages to be relayed to Rialto. +pub type ToRialtoBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter<ToRialtoXcmBlobHauler>, + crate::xcm_config::RialtoNetwork, + (), +>; + +/// To-Rialto XCM hauler. +pub struct ToRialtoXcmBlobHauler; + +impl XcmBlobHauler for ToRialtoXcmBlobHauler { + type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithRialtoMessagesInstance>; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) + .into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bridges/bin/millau/runtime/src/rialto_parachain_messages.rs b/bridges/bin/millau/runtime/src/rialto_parachain_messages.rs index 1cfdc9c8f49..17495e26ae2 100644 --- a/bridges/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -16,14 +16,20 @@ //! Everything required to serve Millau <-> RialtoParachain messages. -use crate::{Runtime, RuntimeCall, RuntimeOrigin, WithRialtoParachainsInstance}; +use crate::{ + Runtime, RuntimeOrigin, WithRialtoParachainMessagesInstance, WithRialtoParachainsInstance, +}; -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto parachain. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -48,16 +54,16 @@ pub type ToRialtoParachainMessageVerifier = messages::source::FromThisChainMessageVerifier<WithRialtoParachainMessageBridge>; /// Message payload for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessagePayload = - messages::target::FromBridgedChainMessagePayload<RuntimeCall>; +pub type FromRialtoParachainMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithRialtoParachainMessageBridge, - xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>, - crate::xcm_config::XcmWeigher, - WeightCredit, ->; +pub type FromRialtoParachainMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_millau::Millau, + bp_rialto::Rialto, + crate::xcm_config::OnMillauBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<crate::DbWeight>, + >; /// Maximal outbound payload size of Millau -> RialtoParachain messages. pub type ToRialtoParachainMaximalOutboundPayloadSize = @@ -68,8 +74,6 @@ pub type ToRialtoParachainMaximalOutboundPayloadSize = pub struct WithRialtoParachainMessageBridge; impl MessageBridge for WithRialtoParachainMessageBridge { - const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; @@ -90,16 +94,7 @@ impl messages::UnderlyingChainProvider for Millau { } impl messages::ThisChainWithMessages for Millau { - type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// RialtoParachain chain from message lane point of view. @@ -116,8 +111,29 @@ impl messages::UnderlyingChainProvider for RialtoParachain { type Chain = bp_rialto_parachain::RialtoParachain; } -impl messages::BridgedChainWithMessages for RialtoParachain { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for RialtoParachain {} + +/// Export XCM messages to be relayed to Rialto. +pub type ToRialtoParachainBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter<ToRialtoParachainXcmBlobHauler>, + crate::xcm_config::RialtoParachainNetwork, + (), +>; + +/// To-RialtoParachain XCM hauler. +pub struct ToRialtoParachainXcmBlobHauler; + +impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { + type MessageSender = + pallet_bridge_messages::Pallet<Runtime, WithRialtoParachainMessagesInstance>; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) + .into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bridges/bin/millau/runtime/src/xcm_config.rs b/bridges/bin/millau/runtime/src/xcm_config.rs index aaaa7bf642d..c477a684526 100644 --- a/bridges/bin/millau/runtime/src/xcm_config.rs +++ b/bridges/bin/millau/runtime/src/xcm_config.rs @@ -17,18 +17,12 @@ //! XCM configurations for the Millau runtime. use super::{ - rialto_messages::{WithRialtoMessageBridge, XCM_LANE}, - rialto_parachain_messages::{WithRialtoParachainMessageBridge, XCM_LANE as XCM_LANE_PARACHAIN}, - AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmPallet, + rialto_messages::ToRialtoBlobExporter, + rialto_parachain_messages::ToRialtoParachainBlobExporter, AccountId, AllPalletsWithSystem, + Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, }; -use bp_messages::LaneId; use bp_millau::WeightToFee; -use bp_rialto_parachain::RIALTO_PARACHAIN_ID; -use bridge_runtime_common::{ - messages::source::{XcmBridge, XcmBridgeAdapter}, - CustomNetworkId, -}; +use bridge_runtime_common::CustomNetworkId; use frame_support::{ parameter_types, traits::{ConstU32, Everything, Nothing}, @@ -36,10 +30,11 @@ use frame_support::{ }; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, }; +use xcm_executor::traits::ExportXcm; parameter_types! { /// The location of the `MLAU` token, from the context of this chain. Since this token is native to this @@ -101,32 +96,28 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our -/// individual routers. -pub type XcmRouter = ( - // Router to send messages to Rialto. - XcmBridgeAdapter<ToRialtoBridge>, - // Router to send messages to RialtoParachains. - XcmBridgeAdapter<ToRialtoParachainBridge>, -); +/// The XCM router. We are not sending messages to sibling/parent/child chains here. +pub type XcmRouter = (); /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( // Weight that is paid for may be consumed. TakeWeightCredit, - // If the message is one that immediately attemps to pay for execution, then allow it. - AllowTopLevelPaidExecutionFrom<Everything>, - // Expected responses are OK. - AllowKnownQueryResponses<XcmPallet>, ); +/// Dispatches received XCM messages from other chain. +pub type OnMillauBlobDispatcher = xcm_builder::BridgeBlobDispatcher< + crate::xcm_config::XcmRouter, + crate::xcm_config::UniversalLocation, +>; + /// XCM weigher type. pub type XcmWeigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type XcmSender = (); type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; type IsReserve = (); @@ -145,7 +136,7 @@ impl xcm_executor::Config for XcmConfig { type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToRialtoOrRialtoParachainSwitchExporter; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -160,7 +151,7 @@ pub type LocalOriginToLocation = ( #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option<MultiLocation> = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); + pub ReachableDest: Option<MultiLocation> = None; } impl pallet_xcm::Config for Runtime { @@ -170,7 +161,7 @@ impl pallet_xcm::Config for Runtime { // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will // make `DescendOrigin` a bit more useful. type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>; - type XcmRouter = XcmRouter; + type XcmRouter = (); // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>; type XcmExecuteFilter = Everything; @@ -197,70 +188,66 @@ impl pallet_xcm::Config for Runtime { type ReachableDest = ReachableDest; } -/// With-Rialto bridge. -pub struct ToRialtoBridge; - -impl XcmBridge for ToRialtoBridge { - type MessageBridge = WithRialtoMessageBridge; - type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithRialtoMessagesInstance>; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() +pub struct ToRialtoOrRialtoParachainSwitchExporter; + +impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { + type Ticket = (NetworkId, (sp_std::prelude::Vec<u8>, XcmHash)); + + fn validate( + network: NetworkId, + channel: u32, + universal_source: &mut Option<InteriorMultiLocation>, + destination: &mut Option<InteriorMultiLocation>, + message: &mut Option<Xcm<()>>, + ) -> SendResult<Self::Ticket> { + if network == RialtoNetwork::get() { + ToRialtoBlobExporter::validate(network, channel, universal_source, destination, message) + .map(|result| ((RialtoNetwork::get(), result.0), result.1)) + } else if network == RialtoParachainNetwork::get() { + ToRialtoParachainBlobExporter::validate( + network, + channel, + universal_source, + destination, + message, + ) + .map(|result| ((RialtoParachainNetwork::get(), result.0), result.1)) + } else { + Err(SendError::Unroutable) + } } - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == RialtoNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = RialtoNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> LaneId { - XCM_LANE - } -} - -/// With-RialtoParachain bridge. -pub struct ToRialtoParachainBridge; - -impl XcmBridge for ToRialtoParachainBridge { - type MessageBridge = WithRialtoParachainMessageBridge; - type MessageSender = - pallet_bridge_messages::Pallet<Runtime, WithRialtoParachainMessagesInstance>; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() - } - - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X2(GlobalConsensus(r), Parachain(RIALTO_PARACHAIN_ID)) } if r == RialtoNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = RialtoParachainNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> LaneId { - XCM_LANE_PARACHAIN + fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> { + let (network, ticket) = ticket; + if network == RialtoNetwork::get() { + ToRialtoBlobExporter::deliver(ticket) + } else if network == RialtoParachainNetwork::get() { + ToRialtoParachainBlobExporter::deliver(ticket) + } else { + Err(SendError::Unroutable) + } } } #[cfg(test)] mod tests { use super::*; - use crate::rialto_messages::WeightCredit; + use crate::{ + rialto_messages::FromRialtoMessageDispatch, + rialto_parachain_messages::FromRialtoParachainMessageDispatch, DbWeight, + WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, + }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - MessageKey, + LaneId, MessageKey, + }; + use bridge_runtime_common::messages_xcm_extension::{ + XcmBlobMessageDispatchResult, XcmRouterWeigher, }; - use bp_runtime::messages::MessageDispatchResult; - use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; use codec::Encode; + use pallet_bridge_messages::OutboundLanes; + use sp_core::Get; + use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -268,59 +255,128 @@ mod tests { ) } + fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm<RuntimeCall> { + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: vec![Instruction::Trap(42)].into(), + }] + .into() + } + #[test] - fn xcm_messages_are_sent_using_bridge_router() { + fn xcm_messages_to_rialto_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); - let expected_hash = - ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - - // message 1 to Rialto - let dest = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))); - let send_result = send_xcm::<XcmRouter>(dest.into(), xcm.clone()); - assert_eq!(send_result, Ok((expected_hash, expected_fee.clone()))); - - // message 2 to RialtoParachain (expected hash is the same, since other lane is used) - let dest = - (Parent, X2(GlobalConsensus(RialtoNetwork::get()), Parachain(RIALTO_PARACHAIN_ID))); - let send_result = send_xcm::<XcmRouter>(dest.into(), xcm); - assert_eq!(send_result, Ok((expected_hash, expected_fee))); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::<Runtime, WithRialtoMessagesInstance>::get( + crate::rialto_messages::XCM_LANE + ) + .latest_generated_nonce, + 0, + ); + + // export message instruction "sends" message to Rialto + XcmExecutor::<XcmConfig>::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(RialtoNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued + assert_eq!( + OutboundLanes::<Runtime, WithRialtoMessagesInstance>::get( + crate::rialto_messages::XCM_LANE + ) + .latest_generated_nonce, + 1, + ); }) } #[test] - fn xcm_messages_from_rialto_are_dispatched() { - type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>; - type MessageDispatcher = FromBridgedChainMessageDispatch< - WithRialtoMessageBridge, - XcmExecutor, - XcmWeigher, - WeightCredit, - >; - + fn xcm_messages_to_rialto_parachain_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - let location: MultiLocation = - (Parent, X1(GlobalConsensus(RialtoNetwork::get()))).into(); - let xcm: Xcm<RuntimeCall> = vec![Instruction::Trap(42)].into(); - - let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()) }, - }; - - let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, BaseXcmWeight::get()); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::<Runtime, WithRialtoParachainMessagesInstance>::get( + crate::rialto_parachain_messages::XCM_LANE + ) + .latest_generated_nonce, + 0, + ); - let dispatch_result = - MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + // export message instruction "sends" message to Rialto + XcmExecutor::<XcmConfig>::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(RialtoParachainNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued assert_eq!( - dispatch_result, - MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::zero(), - dispatch_level_result: (), - } + OutboundLanes::<Runtime, WithRialtoParachainMessagesInstance>::get( + crate::rialto_parachain_messages::XCM_LANE + ) + .latest_generated_nonce, + 1, ); }) } + + fn prepare_inbound_bridge_message() -> DispatchMessage<Vec<u8>> { + let xcm = xcm::VersionedXcm::<RuntimeCall>::V3(vec![Instruction::Trap(42)].into()); + let location = + xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + let bridge_message = (location, xcm).encode(); + DispatchMessage { + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, + data: DispatchMessageData { payload: Ok(bridge_message) }, + } + } + + #[test] + fn xcm_messages_from_rialto_are_dispatched() { + let mut incoming_message = prepare_inbound_bridge_message(); + + let dispatch_weight = FromRialtoMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::<DbWeight>::get()); + + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch + let dispatch_result = + FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + } + + #[test] + fn xcm_messages_from_rialto_parachain_are_dispatched() { + let mut incoming_message = prepare_inbound_bridge_message(); + + let dispatch_weight = + FromRialtoParachainMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::<DbWeight>::get()); + + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch + let dispatch_result = + FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + } } diff --git a/bridges/bin/rialto-parachain/runtime/Cargo.toml b/bridges/bin/rialto-parachain/runtime/Cargo.toml index ec8955e7fd1..ed193b4e681 100644 --- a/bridges/bin/rialto-parachain/runtime/Cargo.toml +++ b/bridges/bin/rialto-parachain/runtime/Cargo.toml @@ -111,6 +111,7 @@ std = [ "frame-support/std", "frame-executive/std", "frame-system/std", + "frame-system-rpc-runtime-api/std", "pallet-balances/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", @@ -118,6 +119,7 @@ std = [ "pallet-timestamp/std", "pallet-sudo/std", "pallet-transaction-payment/std", + "pallet-transaction-payment-rpc-runtime-api/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain/std", diff --git a/bridges/bin/rialto-parachain/runtime/src/lib.rs b/bridges/bin/rialto-parachain/runtime/src/lib.rs index 3614bacdc10..58c6a8c673f 100644 --- a/bridges/bin/rialto-parachain/runtime/src/lib.rs +++ b/bridges/bin/rialto-parachain/runtime/src/lib.rs @@ -26,12 +26,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use crate::millau_messages::{WithMillauMessageBridge, XCM_LANE}; - -use bridge_runtime_common::{ - generate_bridge_reject_obsolete_headers_and_messages, - messages::source::{XcmBridge, XcmBridgeAdapter}, -}; +use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::AnyRelayNumber; use scale_info::TypeInfo; @@ -88,11 +83,10 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, - EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, + AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, + NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; use xcm_executor::{Config, XcmExecutor}; @@ -351,7 +345,7 @@ parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); pub RelayOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); + pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); /// The Millau network ID. pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); /// The RialtoParachain network ID. @@ -412,8 +406,8 @@ pub type XcmOriginToTransactDispatchOrigin = ( // the following constant must match the similar constant in the Millau runtime. parameter_types! { - /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 64 * 1024); + /// The amount of weight an XCM operation takes. We don't care much about those values as we're on testnet. + pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 1024); // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; @@ -428,12 +422,11 @@ match_types! { }; } -pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom<Everything>, - AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>, - // ^^^ Parent & its unit plurality gets free execution -); +pub type Barrier = TakeWeightCredit; + +/// Dispatches received XCM messages from other chain. +pub type OnRialtoParachainBlobDispatcher = + xcm_builder::BridgeBlobDispatcher<XcmRouter, UniversalLocation>; /// XCM weigher type. pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>; @@ -441,7 +434,7 @@ pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstruct pub struct XcmConfig; impl Config for XcmConfig { type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type XcmSender = (); type AssetTransactor = LocalAssetTransactor; type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = NativeAsset; @@ -459,7 +452,7 @@ impl Config for XcmConfig { type AssetLocker = (); type AssetExchanger = (); type FeeManager = (); - type MessageExporter = (); + type MessageExporter = millau_messages::ToMillauBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -468,42 +461,12 @@ impl Config for XcmConfig { /// No local origins on this chain are allowed to dispatch XCM sends/executions. pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>; -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = ( - // Bridge is used to communicate with other relay chain (Millau). - XcmBridgeAdapter<ToMillauBridge>, -); - -/// With-Millau bridge. -pub struct ToMillauBridge; - -impl XcmBridge for ToMillauBridge { - type MessageBridge = WithMillauMessageBridge; - type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithMillauMessagesInstance>; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() - } - - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = MillauNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> bp_messages::LaneId { - XCM_LANE - } -} +/// The XCM router. We are not sending messages to sibling/parent/child chains here. +pub type XcmRouter = (); #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option<MultiLocation> = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); + pub ReachableDest: Option<MultiLocation> = None; } impl pallet_xcm::Config for Runtime { @@ -875,17 +838,20 @@ cumulus_pallet_parachain_system::register_validate_block!( #[cfg(test)] mod tests { use super::*; - use crate::millau_messages::WeightCredit; + use crate::millau_messages::{FromMillauMessageDispatch, XCM_LANE}; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::{ - integrity::check_additional_signed, messages::target::FromBridgedChainMessageDispatch, + integrity::check_additional_signed, + messages_xcm_extension::{XcmBlobMessageDispatchResult, XcmRouterWeigher}, }; use codec::Encode; + use pallet_bridge_messages::OutboundLanes; + use sp_core::Get; use sp_runtime::generic::Era; + use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -893,54 +859,75 @@ mod tests { ) } + fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm<RuntimeCall> { + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: vec![Instruction::Trap(42)].into(), + }] + .into() + } + #[test] - fn xcm_messages_to_millau_are_sent() { + fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - // the encoded message (origin ++ xcm) is 0x010109020419A8 - let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); - let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - - let send_result = send_xcm::<XcmRouter>(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(1_000_000_u128))); - let expected_hash = - ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - assert_eq!(send_result, Ok((expected_hash, expected_fee)),); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::<Runtime, WithMillauMessagesInstance>::get(XCM_LANE) + .latest_generated_nonce, + 0, + ); + + // export message instruction "sends" message to Rialto + XcmExecutor::<XcmConfig>::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(MillauNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued + assert_eq!( + OutboundLanes::<Runtime, WithMillauMessagesInstance>::get(XCM_LANE) + .latest_generated_nonce, + 1, + ); }) } + fn prepare_inbound_bridge_message() -> DispatchMessage<Vec<u8>> { + let xcm = xcm::VersionedXcm::<RuntimeCall>::V3(vec![Instruction::Trap(42)].into()); + let location = + xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + let bridge_message = (location, xcm).encode(); + DispatchMessage { + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, + data: DispatchMessageData { payload: Ok(bridge_message) }, + } + } + #[test] fn xcm_messages_from_millau_are_dispatched() { - type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>; - type MessageDispatcher = FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - XcmExecutor, - XcmWeigher, - WeightCredit, - >; - new_test_ext().execute_with(|| { - let location: MultiLocation = - (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); - let xcm: Xcm<RuntimeCall> = vec![Instruction::Trap(42)].into(); + let mut incoming_message = prepare_inbound_bridge_message(); - let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()) }, - }; - - let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, UnitWeightCost::get()); + let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::<()>::get()); + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch let dispatch_result = - MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); - assert_eq!( - dispatch_result, - MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::zero(), - dispatch_level_result: (), - } - ); - }) + FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + }); } #[test] diff --git a/bridges/bin/rialto-parachain/runtime/src/millau_messages.rs b/bridges/bin/rialto-parachain/runtime/src/millau_messages.rs index ee7a089992e..3fff141bf84 100644 --- a/bridges/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -19,14 +19,18 @@ // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // Should be extracted to a separate crate and reused here. -use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance}; + +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Millau. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -51,15 +55,16 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>; /// Message payload for Millau -> RialtoParachain messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<RuntimeCall>; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. -pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - xcm_executor::XcmExecutor<crate::XcmConfig>, - crate::XcmWeigher, - WeightCredit, ->; +pub type FromMillauMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_rialto_parachain::RialtoParachain, + bp_millau::Millau, + crate::OnRialtoParachainBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<()>, + >; /// Messages proof for Millau -> RialtoParachain messages. pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>; @@ -77,8 +82,6 @@ pub type ToMillauMaximalOutboundPayloadSize = pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const THIS_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; @@ -97,16 +100,7 @@ impl messages::UnderlyingChainProvider for RialtoParachain { } impl messages::ThisChainWithMessages for RialtoParachain { - type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// Millau chain from message lane point of view. @@ -121,8 +115,24 @@ impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } -impl messages::BridgedChainWithMessages for Millau { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for Millau {} + +/// Export XCM messages to be relayed to Millau. +pub type ToMillauBlobExporter = + HaulBlobExporter<XcmBlobHaulerAdapter<ToMillauXcmBlobHauler>, crate::MillauNetwork, ()>; + +/// To-Millau XCM hauler. +pub struct ToMillauXcmBlobHauler; + +impl XcmBlobHauler for ToMillauXcmBlobHauler { + type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithMillauMessagesInstance>; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::UniversalLocation::get())).into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index ff08c08029a..9d0c4f97c89 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -16,14 +16,18 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance}; + +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Lane that is used for XCM messages exchange. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -48,15 +52,16 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>; /// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload<RuntimeCall>; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> Rialto messages. -pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>, - crate::xcm_config::XcmWeigher, - WeightCredit, ->; +pub type FromMillauMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_rialto::Rialto, + bp_millau::Millau, + crate::xcm_config::OnRialtoBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<crate::DbWeight>, + >; /// Messages proof for Millau -> Rialto messages. pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>; @@ -74,8 +79,6 @@ pub type ToMillauMaximalOutboundPayloadSize = pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; type ThisChain = Rialto; @@ -94,15 +97,6 @@ impl messages::UnderlyingChainProvider for Rialto { impl messages::ThisChainWithMessages for Rialto { type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// Millau chain from message lane point of view. @@ -117,9 +111,29 @@ impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } -impl messages::BridgedChainWithMessages for Millau { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for Millau {} + +/// Export XCM messages to be relayed to Millau. +pub type ToMillauBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter<ToMillauXcmBlobHauler>, + crate::xcm_config::MillauNetwork, + (), +>; + +/// To-Millau XCM hauler. +pub struct ToMillauXcmBlobHauler; + +impl XcmBlobHauler for ToMillauXcmBlobHauler { + type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithMillauMessagesInstance>; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) + .into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bridges/bin/rialto/runtime/src/xcm_config.rs b/bridges/bin/rialto/runtime/src/xcm_config.rs index 174ece04725..64a5a896f95 100644 --- a/bridges/bin/rialto/runtime/src/xcm_config.rs +++ b/bridges/bin/rialto/runtime/src/xcm_config.rs @@ -17,14 +17,11 @@ //! XCM configurations for the Rialto runtime. use super::{ - millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, WithMillauMessagesInstance, XcmPallet, + millau_messages::ToMillauBlobExporter, AccountId, AllPalletsWithSystem, Balances, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, }; use bp_rialto::WeightToFee; -use bridge_runtime_common::{ - messages::source::{XcmBridge, XcmBridgeAdapter}, - CustomNetworkId, -}; +use bridge_runtime_common::CustomNetworkId; use frame_support::{ parameter_types, traits::{ConstU32, Everything, Nothing}, @@ -32,9 +29,9 @@ use frame_support::{ }; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, }; parameter_types! { @@ -95,30 +92,28 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our -/// individual routers. -pub type XcmRouter = ( - // Router to send messages to Millau. - XcmBridgeAdapter<ToMillauBridge>, -); +/// The XCM router. We are not sending messages to sibling/parent/child chains here. +pub type XcmRouter = (); /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( // Weight that is paid for may be consumed. TakeWeightCredit, - // If the message is one that immediately attemps to pay for execution, then allow it. - AllowTopLevelPaidExecutionFrom<Everything>, - // Expected responses are OK. - AllowKnownQueryResponses<XcmPallet>, ); +/// Dispatches received XCM messages from other chain. +pub type OnRialtoBlobDispatcher = xcm_builder::BridgeBlobDispatcher< + crate::xcm_config::XcmRouter, + crate::xcm_config::UniversalLocation, +>; + /// Incoming XCM weigher type. pub type XcmWeigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type XcmSender = (); type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; type IsReserve = (); @@ -137,7 +132,7 @@ impl xcm_executor::Config for XcmConfig { type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToMillauBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -152,7 +147,7 @@ pub type LocalOriginToLocation = ( #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option<MultiLocation> = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); + pub ReachableDest: Option<MultiLocation> = None; } impl pallet_xcm::Config for Runtime { @@ -189,43 +184,24 @@ impl pallet_xcm::Config for Runtime { type ReachableDest = ReachableDest; } -/// With-Millau bridge. -pub struct ToMillauBridge; - -impl XcmBridge for ToMillauBridge { - type MessageBridge = WithMillauMessageBridge; - type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithMillauMessagesInstance>; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() - } - - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = MillauNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> bp_messages::LaneId { - bp_messages::LaneId([0, 0, 0, 0]) - } -} - #[cfg(test)] mod tests { use super::*; - use crate::millau_messages::WeightCredit; + use crate::{ + millau_messages::{FromMillauMessageDispatch, XCM_LANE}, + DbWeight, WithMillauMessagesInstance, + }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bp_runtime::messages::MessageDispatchResult; - use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + use bridge_runtime_common::messages_xcm_extension::{ + XcmBlobMessageDispatchResult, XcmRouterWeigher, + }; use codec::Encode; + use pallet_bridge_messages::OutboundLanes; + use sp_core::Get; + use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -233,53 +209,72 @@ mod tests { ) } - #[test] - fn xcm_messages_to_millau_are_sent() { - new_test_ext().execute_with(|| { - // the encoded message (origin ++ xcm) is 0x010109030419A8 - let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); - let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - - let send_result = send_xcm::<XcmRouter>(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); - let expected_hash = - ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - assert_eq!(send_result, Ok((expected_hash, expected_fee)),); - }) + fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm<RuntimeCall> { + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: vec![Instruction::Trap(42)].into(), + }] + .into() } #[test] - fn xcm_messages_from_millau_are_dispatched() { - type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>; - type MessageDispatcher = FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - XcmExecutor, - XcmWeigher, - WeightCredit, - >; - + fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - let location: MultiLocation = - (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); - let xcm: Xcm<RuntimeCall> = vec![Instruction::Trap(42)].into(); - - let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()) }, - }; - - let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, BaseXcmWeight::get()); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::<Runtime, WithMillauMessagesInstance>::get(XCM_LANE) + .latest_generated_nonce, + 0, + ); - let dispatch_result = - MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + // export message instruction "sends" message to Rialto + XcmExecutor::<XcmConfig>::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(MillauNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued assert_eq!( - dispatch_result, - MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::zero(), - dispatch_level_result: (), - } + OutboundLanes::<Runtime, WithMillauMessagesInstance>::get(XCM_LANE) + .latest_generated_nonce, + 1, ); }) } + + fn prepare_inbound_bridge_message() -> DispatchMessage<Vec<u8>> { + let xcm = xcm::VersionedXcm::<RuntimeCall>::V3(vec![Instruction::Trap(42)].into()); + let location = + xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + let bridge_message = (location, xcm).encode(); + DispatchMessage { + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, + data: DispatchMessageData { payload: Ok(bridge_message) }, + } + } + + #[test] + fn xcm_messages_from_millau_are_dispatched() { + let mut incoming_message = prepare_inbound_bridge_message(); + + let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::<DbWeight>::get()); + + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch + let dispatch_result = + FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + } } diff --git a/bridges/bin/runtime-common/src/integrity.rs b/bridges/bin/runtime-common/src/integrity.rs index 5a2c796ee43..96716fe851c 100644 --- a/bridges/bin/runtime-common/src/integrity.rs +++ b/bridges/bin/runtime-common/src/integrity.rs @@ -83,7 +83,7 @@ macro_rules! assert_bridge_messages_pallet_types( use $crate::messages::{ source::{FromThisChainMessagePayload, TargetHeaderChainAdapter}, target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter}, - AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, + AccountIdOf, BalanceOf, BridgedChain, ThisChain, }; use pallet_bridge_messages::Config as MessagesConfig; use static_assertions::assert_type_eq_all; diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index 4493ac66742..9d2e5811380 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -25,28 +25,18 @@ pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider}; use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ source_chain::{LaneMessageVerifier, TargetHeaderChain}, - target_chain::{ - DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, - }, + target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; -use bp_runtime::{ - messages::MessageDispatchResult, Chain, ChainId, RawStorageProof, Size, StorageProofChecker, - StorageProofError, -}; -use codec::{Decode, DecodeLimit, Encode}; +use bp_runtime::{Chain, RawStorageProof, Size, StorageProofChecker, StorageProofError}; +use codec::{Decode, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; -use xcm::latest::prelude::*; /// Bidirectional message bridge. pub trait MessageBridge { - /// Identifier of this chain. - const THIS_CHAIN_ID: ChainId; - /// Identifier of the Bridged chain. - const BRIDGED_CHAIN_ID: ChainId; /// Name of the paired messages pallet instance at the Bridged chain. /// /// Should be the name that is used in the `construct_runtime!()` macro. @@ -64,24 +54,10 @@ pub trait MessageBridge { pub trait ThisChainWithMessages: UnderlyingChainProvider { /// Call origin on the chain. type RuntimeOrigin; - /// Call type on the chain. - type RuntimeCall: Encode + Decode; - - /// Do we accept message sent by given origin to given lane? - fn is_message_accepted(origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool; - - /// Maximal number of pending (not yet delivered) messages at This chain. - /// - /// Any messages over this limit, will be rejected. - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; } /// Bridged chain that has `pallet-bridge-messages` module. -pub trait BridgedChainWithMessages: UnderlyingChainProvider { - /// Returns `true` if message dispatch weight is withing expected limits. `false` means - /// that the message is too heavy to be sent over the bridge and shall be rejected. - fn verify_dispatch_weight(message_payload: &[u8]) -> bool; -} +pub trait BridgedChainWithMessages: UnderlyingChainProvider {} /// This chain in context of message bridge. pub type ThisChain<B> = <B as MessageBridge>::ThisChain; @@ -97,8 +73,6 @@ pub type AccountIdOf<C> = bp_runtime::AccountIdOf<UnderlyingChainOf<C>>; pub type BalanceOf<C> = bp_runtime::BalanceOf<UnderlyingChainOf<C>>; /// Type of origin that is used on the chain. pub type OriginOf<C> = <C as ThisChainWithMessages>::RuntimeOrigin; -/// Type of call that is used on this chain. -pub type CallOf<C> = <C as ThisChainWithMessages>::RuntimeCall; /// Error that happens during message verification. #[derive(Debug, PartialEq, Eq)] @@ -128,7 +102,7 @@ pub mod source { use super::*; /// Message payload for This -> Bridged chain messages. - pub type FromThisChainMessagePayload = Vec<u8>; + pub type FromThisChainMessagePayload = crate::messages_xcm_extension::XcmAsPlainPayload; /// Maximal size of outbound message payload. pub struct FromThisChainMaximalOutboundPayloadSize<B>(PhantomData<B>); @@ -186,13 +160,6 @@ pub mod source { #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier<B>(PhantomData<B>); - /// The error message returned from `LaneMessageVerifier` when outbound lane is disabled. - pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = - "The outbound message lane has rejected the message."; - /// The error message returned from `LaneMessageVerifier` when too many pending messages at the - /// lane. - pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; - impl<B> LaneMessageVerifier<OriginOf<ThisChain<B>>, FromThisChainMessagePayload> for FromThisChainMessageVerifier<B> where @@ -205,24 +172,16 @@ pub mod source { type Error = &'static str; fn verify_message( - submitter: &OriginOf<ThisChain<B>>, - lane: &LaneId, - lane_outbound_data: &OutboundLaneData, + _submitter: &OriginOf<ThisChain<B>>, + _lane: &LaneId, + _lane_outbound_data: &OutboundLaneData, _payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { - // reject message if lane is blocked - if !ThisChain::<B>::is_message_accepted(submitter, lane) { - return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE) - } - - // reject message if there are too many pending messages at this lane - let max_pending_messages = ThisChain::<B>::maximal_pending_messages_at_outbound_lane(); - let pending_messages = lane_outbound_data - .latest_generated_nonce - .saturating_sub(lane_outbound_data.latest_received_nonce); - if pending_messages > max_pending_messages { - return Err(TOO_MANY_PENDING_MESSAGES) - } + // IMPORTANT: any error that is returned here is fatal for the bridge, because + // this code is executed at the bridge hub and message sender actually lives + // at some sibling parachain. So we are failing **after** the message has been + // sent and we can't report it back to sender (unless error report mechanism is + // embedded into message and its dispatcher). Ok(()) } @@ -263,9 +222,15 @@ pub mod source { pub fn verify_chain_message<B: MessageBridge>( payload: &FromThisChainMessagePayload, ) -> Result<(), Error> { - if !BridgedChain::<B>::verify_dispatch_weight(payload) { - return Err(Error::InvalidMessageWeight) - } + // IMPORTANT: any error that is returned here is fatal for the bridge, because + // this code is executed at the bridge hub and message sender actually lives + // at some sibling parachain. So we are failing **after** the message has been + // sent and we can't report it back to sender (unless error report mechanism is + // embedded into message and its dispatcher). + + // apart from maximal message size check (see below), we should also check the message + // dispatch weight here. But we assume that the bridged chain will just push the message + // to some queue (XCMP, UMP, DMP), so the weight is constant and fits the block. // The maximal size of extrinsic at Substrate-based chain depends on the // `frame_system::Config::MaximumBlockLength` and @@ -316,92 +281,6 @@ pub mod source { ) .map_err(Error::HeaderChain)? } - - /// XCM bridge. - pub trait XcmBridge { - /// Runtime message bridge configuration. - type MessageBridge: MessageBridge; - /// Runtime message sender adapter. - type MessageSender: bp_messages::source_chain::MessagesBridge< - OriginOf<ThisChain<Self::MessageBridge>>, - FromThisChainMessagePayload, - >; - - /// Our location within the Consensus Universe. - fn universal_location() -> InteriorMultiLocation; - /// Verify that the adapter is responsible for handling given XCM destination. - fn verify_destination(dest: &MultiLocation) -> bool; - /// Build route from this chain to the XCM destination. - fn build_destination() -> MultiLocation; - /// Return message lane used to deliver XCM messages. - fn xcm_lane() -> LaneId; - } - - /// XCM bridge adapter for `bridge-messages` pallet. - pub struct XcmBridgeAdapter<T>(PhantomData<T>); - - impl<T: XcmBridge> SendXcm for XcmBridgeAdapter<T> - where - BalanceOf<ThisChain<T::MessageBridge>>: Into<Fungibility>, - OriginOf<ThisChain<T::MessageBridge>>: From<pallet_xcm::Origin>, - { - type Ticket = FromThisChainMessagePayload; - - fn validate( - dest: &mut Option<MultiLocation>, - msg: &mut Option<Xcm<()>>, - ) -> SendResult<Self::Ticket> { - let d = dest.take().ok_or(SendError::MissingArgument)?; - if !T::verify_destination(&d) { - *dest = Some(d); - return Err(SendError::NotApplicable) - } - - let route = T::build_destination(); - let msg = (route, msg.take().ok_or(SendError::MissingArgument)?).encode(); - - // let's just take fixed (out of thin air) fee per message in our test bridges - // (this code won't be used in production anyway) - let fee_assets = MultiAssets::from((Here, 1_000_000_u128)); - - Ok((msg, fee_assets)) - } - - fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> { - use bp_messages::source_chain::MessagesBridge; - - let lane = T::xcm_lane(); - let msg = ticket; - let result = T::MessageSender::send_message( - pallet_xcm::Origin::from(MultiLocation::from(T::universal_location())).into(), - lane, - msg, - ); - result - .map(|artifacts| { - let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); - log::debug!( - target: "runtime::bridge", - "Sent XCM message {:?}/{} to {:?}: {:?}", - lane, - artifacts.nonce, - T::MessageBridge::BRIDGED_CHAIN_ID, - hash, - ); - hash - }) - .map_err(|e| { - log::debug!( - target: "runtime::bridge", - "Failed to send XCM message over lane {:?} to {:?}: {:?}", - lane, - T::MessageBridge::BRIDGED_CHAIN_ID, - e, - ); - SendError::Transport("Bridge has rejected the message") - }) - } - } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages. @@ -409,35 +288,7 @@ pub mod target { use super::*; /// Decoded Bridged -> This message payload. - #[derive(RuntimeDebug, PartialEq, Eq)] - pub struct FromBridgedChainMessagePayload<Call> { - /// Data that is actually sent over the wire. - pub xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm<Call>), - /// Weight of the message, computed by the weigher. Unknown initially. - pub weight: Option<Weight>, - } - - impl<Call: Decode> Decode for FromBridgedChainMessagePayload<Call> { - fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> { - let _: codec::Compact<u32> = Decode::decode(input)?; - type XcmPairType<Call> = (xcm::v3::MultiLocation, xcm::v3::Xcm<Call>); - Ok(FromBridgedChainMessagePayload { - xcm: XcmPairType::<Call>::decode_with_depth_limit( - sp_api::MAX_EXTRINSIC_DEPTH, - input, - )?, - weight: None, - }) - } - } - - impl<Call> From<(xcm::v3::MultiLocation, xcm::v3::Xcm<Call>)> - for FromBridgedChainMessagePayload<Call> - { - fn from(xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm<Call>)) -> Self { - FromBridgedChainMessagePayload { xcm, weight: None } - } - } + pub type FromBridgedChainMessagePayload = crate::messages_xcm_extension::XcmAsPlainPayload; /// Messages proof from bridged chain: /// @@ -470,118 +321,6 @@ pub mod target { } } - /// Dispatching Bridged -> This chain messages. - #[derive(RuntimeDebug, Clone, Copy)] - pub struct FromBridgedChainMessageDispatch<B, XcmExecutor, XcmWeigher, WeightCredit> { - _marker: PhantomData<(B, XcmExecutor, XcmWeigher, WeightCredit)>, - } - - impl<B: MessageBridge, XcmExecutor, XcmWeigher, WeightCredit> - MessageDispatch<AccountIdOf<ThisChain<B>>> - for FromBridgedChainMessageDispatch<B, XcmExecutor, XcmWeigher, WeightCredit> - where - XcmExecutor: xcm::v3::ExecuteXcm<CallOf<ThisChain<B>>>, - XcmWeigher: xcm_executor::traits::WeightBounds<CallOf<ThisChain<B>>>, - WeightCredit: Get<Weight>, - { - type DispatchPayload = FromBridgedChainMessagePayload<CallOf<ThisChain<B>>>; - type DispatchLevelResult = (); - - fn dispatch_weight( - message: &mut DispatchMessage<Self::DispatchPayload>, - ) -> frame_support::weights::Weight { - match message.data.payload { - Ok(ref mut payload) => { - // I have no idea why this method takes `&mut` reference and there's nothing - // about that in documentation. Hope it'll only mutate iff error is returned. - let weight = XcmWeigher::weight(&mut payload.xcm.1); - let weight = weight.unwrap_or_else(|e| { - log::debug!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}", - message.key.lane_id, - message.key.nonce, - e, - ); - - // we shall return 0 and then the XCM executor will fail to execute XCM - // if we'll return something else (e.g. maximal value), the lane may stuck - Weight::zero() - }); - - payload.weight = Some(weight); - weight - }, - _ => Weight::zero(), - } - } - - fn dispatch( - _relayer_account: &AccountIdOf<ThisChain<B>>, - message: DispatchMessage<Self::DispatchPayload>, - ) -> MessageDispatchResult<Self::DispatchLevelResult> { - let message_id = (message.key.lane_id, message.key.nonce); - let do_dispatch = move || -> sp_std::result::Result<Outcome, codec::Error> { - let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } = - message.data.payload?; - log::trace!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Going to execute message {:?} (weight limit: {:?}): {:?} {:?}", - message_id, - weight_limit, - location, - xcm, - ); - let hash = message_id.using_encoded(sp_io::hashing::blake2_256); - - // if this cod will end up in production, this most likely needs to be set to zero - let weight_credit = WeightCredit::get(); - - let xcm_outcome = XcmExecutor::execute_xcm_in_credit( - location, - xcm, - hash, - weight_limit.unwrap_or_else(Weight::zero), - weight_credit, - ); - Ok(xcm_outcome) - }; - - let xcm_outcome = do_dispatch(); - match xcm_outcome { - Ok(outcome) => { - log::trace!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Incoming message {:?} dispatched with result: {:?}", - message_id, - outcome, - ); - match outcome.ensure_execution() { - Ok(_weight) => (), - Err(e) => { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Incoming message {:?} was not dispatched, error: {:?}", - message_id, - e, - ); - }, - } - }, - Err(e) => { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Incoming message {:?} was not dispatched, codec error: {:?}", - message_id, - e, - ); - }, - } - - MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } - } - } - /// 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 @@ -745,54 +484,6 @@ mod tests { use sp_core::H256; use sp_runtime::traits::Header as _; - fn test_lane_outbound_data() -> OutboundLaneData { - OutboundLaneData::default() - } - - fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { - vec![42] - } - - #[test] - fn message_is_rejected_when_sent_using_disabled_lane() { - assert_eq!( - source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message( - &frame_system::RawOrigin::Root.into(), - &LaneId(*b"dsbl"), - &test_lane_outbound_data(), - ®ular_outbound_message_payload(), - ), - Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE) - ); - } - - #[test] - fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { - assert_eq!( - source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message( - &frame_system::RawOrigin::Root.into(), - &TEST_LANE_ID, - &OutboundLaneData { - latest_received_nonce: 100, - latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1, - ..Default::default() - }, - ®ular_outbound_message_payload(), - ), - Err(source::TOO_MANY_PENDING_MESSAGES) - ); - } - - #[test] - fn verify_chain_message_rejects_message_with_too_small_declared_weight() { - assert!(source::verify_chain_message::<OnThisChainBridge>(&vec![ - 42; - BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT - - 1 - ]) - .is_err()); - } - #[test] fn verify_chain_message_rejects_message_with_too_large_declared_weight() { assert!(source::verify_chain_message::<OnThisChainBridge>(&vec![ diff --git a/bridges/bin/runtime-common/src/messages_xcm_extension.rs b/bridges/bin/runtime-common/src/messages_xcm_extension.rs index 42ac67a0f26..a8ca86c85c3 100644 --- a/bridges/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bridges/bin/runtime-common/src/messages_xcm_extension.rs @@ -28,13 +28,43 @@ use bp_messages::{ }; use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; use codec::{Decode, Encode}; -use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound}; +use frame_support::{ + dispatch::Weight, traits::Get, weights::RuntimeDbWeight, CloneNoBound, EqNoBound, + PartialEqNoBound, +}; use scale_info::TypeInfo; +use sp_std::marker::PhantomData; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; /// Plain "XCM" payload, which we transfer through bridge pub type XcmAsPlainPayload = sp_std::prelude::Vec<u8>; +// TODO: below are just rough estimations. Other things also happen there (including hashing and so +// on). Shall we do some benchmarking??? TODO: add proof_size component here +// https://github.com/paritytech/parity-bridges-common/issues/1986 + +/// Simple weigher for incoming XCM dispatch at **bridge hubs** to use with +/// `XcmBlobMessageDispatch`. +/// +/// By our design, message at bridge hub is simply pushed to some other queue. This implementation +/// is for this case only. If your runtime performs some other actions with incoming XCM messages, +/// you shall use your own implementation. +/// +/// If message is redirected to the relay chain, then `ParentAsUmp` is used and it roughly does +/// 1 db read and 1 db write (in its `send_upward_message` method). +/// +/// If message is redirected to some sibling parachain, then `XcmpQueue` is used and +/// it roughly does 2 db reads and 2 db writes (in its `SendXcm` implementation). +/// +/// The difference is not that big, so let's choose maximal. +pub struct XcmRouterWeigher<T>(PhantomData<T>); + +impl<T: Get<RuntimeDbWeight>> Get<Weight> for XcmRouterWeigher<T> { + fn get() -> Weight { + T::get().reads_writes(2, 2) + } +} + /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] pub enum XcmBlobMessageDispatchResult { diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index 056fd3a2ccf..5c2c967c060 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -33,7 +33,7 @@ use crate::messages::{ }; use bp_header_chain::{ChainWithGrandpa, HeaderChain}; -use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; +use bp_messages::{target_chain::ForbidInboundMessages, LaneId}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; use codec::{Decode, Encode}; @@ -87,10 +87,6 @@ pub type BridgedChainHeader = pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); /// Bridged chain id used in tests. pub const TEST_BRIDGED_CHAIN_ID: ChainId = *b"brdg"; -/// Maximal number of queued messages at the test lane. -pub const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; -/// Minimal extrinsic weight at the `BridgedChain`. -pub const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; /// Maximal extrinsic weight at the `BridgedChain`. pub const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; /// Maximal extrinsic size at the `BridgedChain`. @@ -222,7 +218,7 @@ impl pallet_bridge_messages::Config for TestRuntime { type MaximalOutboundPayloadSize = FromThisChainMaximalOutboundPayloadSize<OnThisChainBridge>; type OutboundPayload = FromThisChainMessagePayload; - type InboundPayload = FromBridgedChainMessagePayload<ThisChainRuntimeCall>; + type InboundPayload = FromBridgedChainMessagePayload; type InboundRelayer = BridgedChainAccountId; type DeliveryPayments = (); @@ -235,8 +231,7 @@ impl pallet_bridge_messages::Config for TestRuntime { >; type SourceHeaderChain = SourceHeaderChainAdapter<OnThisChainBridge>; - type MessageDispatch = - ForbidInboundMessages<(), FromBridgedChainMessagePayload<ThisChainRuntimeCall>>; + type MessageDispatch = ForbidInboundMessages<(), FromBridgedChainMessagePayload>; type BridgedChainId = BridgedChainId; } @@ -253,8 +248,6 @@ impl pallet_bridge_relayers::Config for TestRuntime { pub struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { - const THIS_CHAIN_ID: ChainId = *b"this"; - const BRIDGED_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = ThisChain; @@ -268,8 +261,6 @@ impl MessageBridge for OnThisChainBridge { pub struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { - const THIS_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = *b"this"; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = BridgedChain; @@ -331,22 +322,9 @@ impl UnderlyingChainProvider for ThisChain { impl ThisChainWithMessages for ThisChain { type RuntimeOrigin = ThisChainCallOrigin; - type RuntimeCall = ThisChainRuntimeCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - *lane == TEST_LANE_ID - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE - } } -impl BridgedChainWithMessages for ThisChain { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - unreachable!() - } -} +impl BridgedChainWithMessages for ThisChain {} /// Underlying chain of `BridgedChain`. pub struct BridgedUnderlyingChain; @@ -413,20 +391,6 @@ impl UnderlyingChainProvider for BridgedChain { impl ThisChainWithMessages for BridgedChain { type RuntimeOrigin = BridgedChainOrigin; - type RuntimeCall = BridgedChainCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - unreachable!() - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - unreachable!() - } } -impl BridgedChainWithMessages for BridgedChain { - fn verify_dispatch_weight(message_payload: &[u8]) -> bool { - message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && - message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT - } -} +impl BridgedChainWithMessages for BridgedChain {} diff --git a/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs index 1d2373de6d3..d4f551ce57a 100644 --- a/bridges/primitives/runtime/src/lib.rs +++ b/bridges/primitives/runtime/src/lib.rs @@ -502,11 +502,11 @@ pub struct StrippableError<T> { } impl<T: Debug> From<T> for StrippableError<T> { - fn from(err: T) -> Self { + fn from(_err: T) -> Self { Self { _phantom_data: Default::default(), #[cfg(feature = "std")] - message: format!("{:?}", err), + message: format!("{:?}", _err), } } } diff --git a/bridges/relays/bin-substrate/src/chains/millau.rs b/bridges/relays/bin-substrate/src/chains/millau.rs index ca9a32a48a5..44416195c6a 100644 --- a/bridges/relays/bin-substrate/src/chains/millau.rs +++ b/bridges/relays/bin-substrate/src/chains/millau.rs @@ -16,37 +16,18 @@ //! Millau chain specification for CLI. -use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; -use bp_rialto_parachain::RIALTO_PARACHAIN_ID; +use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_millau_client::Millau; use relay_substrate_client::SimpleRuntimeVersion; -use xcm::latest::prelude::*; impl CliEncodeMessage for Millau { - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + fn encode_execute_xcm( + message: xcm::VersionedXcm<Self::Call>, ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> { - let dest = match bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => - (Parent, X1(GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()))), - bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => ( - Parent, - X2( - GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()), - Parachain(RIALTO_PARACHAIN_ID), - ), - ), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }; - - Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::send { - dest: Box::new(dest.into()), + Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::execute { message: Box::new(message), + max_weight: Self::estimate_execute_xcm_weight(), }) .into()) } diff --git a/bridges/relays/bin-substrate/src/chains/rialto.rs b/bridges/relays/bin-substrate/src/chains/rialto.rs index e9e2d0b3eaf..34a448ae4cb 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto.rs @@ -16,29 +16,18 @@ //! Rialto chain specification for CLI. -use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; +use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_rialto_client::Rialto; use relay_substrate_client::SimpleRuntimeVersion; -use xcm::latest::prelude::*; impl CliEncodeMessage for Rialto { - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + fn encode_execute_xcm( + message: xcm::VersionedXcm<Self::Call>, ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> { - let dest = match bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => - (Parent, X1(GlobalConsensus(rialto_runtime::xcm_config::MillauNetwork::get()))), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }; - - Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::send { - dest: Box::new(dest.into()), + Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::execute { message: Box::new(message), + max_weight: Self::estimate_execute_xcm_weight(), }) .into()) } diff --git a/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs b/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs index 1a5ea2e784e..8ea2c1ffd43 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -16,33 +16,21 @@ //! Rialto parachain specification for CLI. -use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; +use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; -use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; use relay_substrate_client::SimpleRuntimeVersion; -use xcm::latest::prelude::*; impl CliEncodeMessage for RialtoParachain { - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + fn encode_execute_xcm( + message: xcm::VersionedXcm<Self::Call>, ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> { type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; type XcmCall = relay_rialto_parachain_client::runtime_types::pallet_xcm::pallet::Call; - let dest = match bridge_instance_index { - bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => - (Parent, X1(GlobalConsensus(CustomNetworkId::Millau.as_network_id()))), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }; - - let xcm_call = XcmCall::send { - dest: Box::new(unsafe { std::mem::transmute(xcm::VersionedMultiLocation::from(dest)) }), + let xcm_call = XcmCall::execute { message: Box::new(unsafe { std::mem::transmute(message) }), + max_weight: Self::estimate_execute_xcm_weight(), }; Ok(RuntimeCall::PolkadotXcm(xcm_call).into()) diff --git a/bridges/relays/bin-substrate/src/cli/bridge.rs b/bridges/relays/bin-substrate/src/cli/bridge.rs index a3cacec3313..62c71183a48 100644 --- a/bridges/relays/bin-substrate/src/cli/bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/bridge.rs @@ -37,28 +37,6 @@ pub enum FullBridge { BridgeHubPolkadotToBridgeHubKusama, } -impl FullBridge { - /// Return instance index of the bridge pallet in source runtime. - pub fn bridge_instance_index(&self) -> u8 { - match self { - Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, - Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, - Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, - Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, - Self::BridgeHubRococoToBridgeHubWococo | - Self::BridgeHubWococoToBridgeHubRococo | - Self::BridgeHubKusamaToBridgeHubPolkadot | - Self::BridgeHubPolkadotToBridgeHubKusama => - unimplemented!("Relay doesn't support send-message subcommand on bridge hubs"), - } - } -} - -pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; -pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; -pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1; -pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; - /// Minimal bridge representation that can be used from the CLI. /// It connects a source chain to a target chain. pub trait CliBridgeBase: Sized { diff --git a/bridges/relays/bin-substrate/src/cli/encode_message.rs b/bridges/relays/bin-substrate/src/cli/encode_message.rs index c7ca5d51f79..9abf8b2df6d 100644 --- a/bridges/relays/bin-substrate/src/cli/encode_message.rs +++ b/bridges/relays/bin-substrate/src/cli/encode_message.rs @@ -17,6 +17,7 @@ use crate::cli::{ExplicitOrMaximal, HexBytes}; use bp_runtime::EncodedOrDecodedCall; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -42,11 +43,16 @@ pub enum Message { pub type RawMessage = Vec<u8>; pub trait CliEncodeMessage: Chain { - /// Encode a send XCM call of the XCM pallet. - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + /// Encode an `execute` XCM call of the XCM pallet. + fn encode_execute_xcm( + message: xcm::VersionedXcm<Self::Call>, ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>>; + + /// Estimate value of `max_weight` argument for the `execute` XCM call of the XCM pallet. + fn estimate_execute_xcm_weight() -> Weight { + // we are only executing XCM on our testnets and 1/100 of max extrinsic weight is ok + Self::max_extrinsic_weight() / 100 + } } /// Encode message payload passed through CLI flags. @@ -125,7 +131,7 @@ mod tests { .unwrap(); assert_eq!(msg.len(), 100); // check that it decodes to valid xcm - let _ = decode_xcm(msg).unwrap(); + let _ = decode_xcm::<()>(msg).unwrap(); } #[test] @@ -140,6 +146,6 @@ mod tests { .unwrap(); assert_eq!(msg.len(), maximal_size as usize); // check that it decodes to valid xcm - let _ = decode_xcm(msg).unwrap(); + let _ = decode_xcm::<()>(msg).unwrap(); } } diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index 09d7f72b7f4..8f76e501f69 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -75,10 +75,7 @@ where let source_sign = data.source_sign.to_keypair::<Self::Source>()?; let payload_len = payload.encoded_size(); - let send_message_call = Self::Source::encode_send_xcm( - decode_xcm(payload)?, - data.bridge.bridge_instance_index(), - )?; + let send_message_call = Self::Source::encode_execute_xcm(decode_xcm(payload)?)?; source_client .submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| { @@ -130,7 +127,7 @@ impl SendMessage { } /// Decode SCALE encoded raw XCM message. -pub(crate) fn decode_xcm(message: RawMessage) -> anyhow::Result<xcm::VersionedXcm<()>> { +pub(crate) fn decode_xcm<Call>(message: RawMessage) -> anyhow::Result<xcm::VersionedXcm<Call>> { Decode::decode(&mut &message[..]) .map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e)) } -- GitLab