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
This commit is contained in:
Svyatoslav Nikolsky
2023-03-23 10:44:53 +03:00
committed by Bastian Köcher
parent 2407228972
commit a75c28d5b2
21 changed files with 604 additions and 889 deletions
+5 -4
View File
@@ -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: 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... TRACE bridge Sent transaction to Millau node: 0x5e68...
``` ```
And at the Rialto node logs you'll something like this: 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-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: 48559)/Weight(ref_time: 1215065371, proof_size: 54703).
... runtime::bridge-dispatch: Incoming message ([0, 0, 0, 0], 1) dispatched with result: Incomplete(2000000000, Trap(43))
``` ```
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 ## Full Network Docker Compose Setup
+2 -6
View File
@@ -1021,10 +1021,8 @@ impl_runtime_apis! {
} }
fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool {
use bridge_runtime_common::messages::MessageBridge;
let lane = <Self as MessagesConfig<WithRialtoParachainMessagesInstance>>::bench_lane_id(); 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( pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
relayer, relayer,
RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain)
@@ -1054,10 +1052,8 @@ impl_runtime_apis! {
} }
fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool {
use bridge_runtime_common::messages::MessageBridge;
let lane = <Self as MessagesConfig<WithRialtoMessagesInstance>>::bench_lane_id(); 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( pallet_bridge_relayers::Pallet::<Runtime>::relayer_reward(
relayer, relayer,
RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain)
@@ -16,14 +16,18 @@
//! Everything required to serve Millau <-> Rialto messages. //! Everything required to serve Millau <-> Rialto messages.
use crate::{RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use crate::{RialtoGrandpaInstance, Runtime, RuntimeOrigin, WithRialtoMessagesInstance};
use bp_messages::{LaneId, MessageNonce}; use bp_messages::LaneId;
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::{
use bridge_runtime_common::messages::{ messages::{
self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge,
},
messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter},
}; };
use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; 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. /// Default lane that is used to send messages to Rialto.
pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]);
@@ -48,7 +52,7 @@ pub type ToRialtoMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithRialtoMessageBridge>; messages::source::FromThisChainMessageVerifier<WithRialtoMessageBridge>;
/// Message payload for Rialto -> Millau messages. /// 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. /// Messages proof for Rialto -> Millau messages.
pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_rialto::Hash>; pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_rialto::Hash>;
@@ -58,12 +62,13 @@ pub type ToRialtoMessagesDeliveryProof =
messages::source::FromBridgedChainMessagesDeliveryProof<bp_rialto::Hash>; messages::source::FromBridgedChainMessagesDeliveryProof<bp_rialto::Hash>;
/// Call-dispatch based message dispatch for Rialto -> Millau messages. /// Call-dispatch based message dispatch for Rialto -> Millau messages.
pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< pub type FromRialtoMessageDispatch =
WithRialtoMessageBridge, bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch<
xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>, bp_millau::Millau,
crate::xcm_config::XcmWeigher, bp_rialto::Rialto,
WeightCredit, crate::xcm_config::OnMillauBlobDispatcher,
>; bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<crate::DbWeight>,
>;
/// Maximal outbound payload size of Millau -> Rialto messages. /// Maximal outbound payload size of Millau -> Rialto messages.
pub type ToRialtoMaximalOutboundPayloadSize = pub type ToRialtoMaximalOutboundPayloadSize =
@@ -74,8 +79,6 @@ pub type ToRialtoMaximalOutboundPayloadSize =
pub struct WithRialtoMessageBridge; pub struct WithRialtoMessageBridge;
impl MessageBridge for 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; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME;
type ThisChain = Millau; type ThisChain = Millau;
@@ -94,15 +97,6 @@ impl messages::UnderlyingChainProvider for Millau {
impl messages::ThisChainWithMessages for Millau { impl messages::ThisChainWithMessages for Millau {
type RuntimeOrigin = RuntimeOrigin; 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. /// Rialto chain from message lane point of view.
@@ -117,9 +111,29 @@ impl messages::UnderlyingChainProvider for Rialto {
type Chain = bp_rialto::Rialto; type Chain = bp_rialto::Rialto;
} }
impl messages::BridgedChainWithMessages for Rialto { impl messages::BridgedChainWithMessages for Rialto {}
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
true /// 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
} }
} }
@@ -16,14 +16,20 @@
//! Everything required to serve Millau <-> RialtoParachain messages. //! 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_messages::LaneId;
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; use bridge_runtime_common::{
use bridge_runtime_common::messages::{ messages::{
self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge,
},
messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter},
}; };
use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; 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. /// Default lane that is used to send messages to Rialto parachain.
pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]);
@@ -48,16 +54,16 @@ pub type ToRialtoParachainMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithRialtoParachainMessageBridge>; messages::source::FromThisChainMessageVerifier<WithRialtoParachainMessageBridge>;
/// Message payload for RialtoParachain -> Millau messages. /// Message payload for RialtoParachain -> Millau messages.
pub type FromRialtoParachainMessagePayload = pub type FromRialtoParachainMessagePayload = messages::target::FromBridgedChainMessagePayload;
messages::target::FromBridgedChainMessagePayload<RuntimeCall>;
/// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. /// Call-dispatch based message dispatch for RialtoParachain -> Millau messages.
pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChainMessageDispatch< pub type FromRialtoParachainMessageDispatch =
WithRialtoParachainMessageBridge, bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch<
xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>, bp_millau::Millau,
crate::xcm_config::XcmWeigher, bp_rialto::Rialto,
WeightCredit, crate::xcm_config::OnMillauBlobDispatcher,
>; bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<crate::DbWeight>,
>;
/// Maximal outbound payload size of Millau -> RialtoParachain messages. /// Maximal outbound payload size of Millau -> RialtoParachain messages.
pub type ToRialtoParachainMaximalOutboundPayloadSize = pub type ToRialtoParachainMaximalOutboundPayloadSize =
@@ -68,8 +74,6 @@ pub type ToRialtoParachainMaximalOutboundPayloadSize =
pub struct WithRialtoParachainMessageBridge; pub struct WithRialtoParachainMessageBridge;
impl MessageBridge for 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; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME;
type ThisChain = Millau; type ThisChain = Millau;
@@ -90,16 +94,7 @@ impl messages::UnderlyingChainProvider for Millau {
} }
impl messages::ThisChainWithMessages for Millau { impl messages::ThisChainWithMessages for Millau {
type RuntimeCall = RuntimeCall;
type RuntimeOrigin = RuntimeOrigin; 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. /// RialtoParachain chain from message lane point of view.
@@ -116,8 +111,29 @@ impl messages::UnderlyingChainProvider for RialtoParachain {
type Chain = bp_rialto_parachain::RialtoParachain; type Chain = bp_rialto_parachain::RialtoParachain;
} }
impl messages::BridgedChainWithMessages for RialtoParachain { impl messages::BridgedChainWithMessages for RialtoParachain {}
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
true /// 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
} }
} }
+176 -120
View File
@@ -17,18 +17,12 @@
//! XCM configurations for the Millau runtime. //! XCM configurations for the Millau runtime.
use super::{ use super::{
rialto_messages::{WithRialtoMessageBridge, XCM_LANE}, rialto_messages::ToRialtoBlobExporter,
rialto_parachain_messages::{WithRialtoParachainMessageBridge, XCM_LANE as XCM_LANE_PARACHAIN}, rialto_parachain_messages::ToRialtoParachainBlobExporter, AccountId, AllPalletsWithSystem,
AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet,
WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmPallet,
}; };
use bp_messages::LaneId;
use bp_millau::WeightToFee; use bp_millau::WeightToFee;
use bp_rialto_parachain::RIALTO_PARACHAIN_ID; use bridge_runtime_common::CustomNetworkId;
use bridge_runtime_common::{
messages::source::{XcmBridge, XcmBridgeAdapter},
CustomNetworkId,
};
use frame_support::{ use frame_support::{
parameter_types, parameter_types,
traits::{ConstU32, Everything, Nothing}, traits::{ConstU32, Everything, Nothing},
@@ -36,10 +30,11 @@ use frame_support::{
}; };
use xcm::latest::prelude::*; use xcm::latest::prelude::*;
use xcm_builder::{ use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation,
CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, UsingComponents,
}; };
use xcm_executor::traits::ExportXcm;
parameter_types! { parameter_types! {
/// The location of the `MLAU` token, from the context of this chain. Since this token is native to this /// 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; 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 /// The XCM router. We are not sending messages to sibling/parent/child chains here.
/// individual routers. pub type XcmRouter = ();
pub type XcmRouter = (
// Router to send messages to Rialto.
XcmBridgeAdapter<ToRialtoBridge>,
// Router to send messages to RialtoParachains.
XcmBridgeAdapter<ToRialtoParachainBridge>,
);
/// The barriers one of which must be passed for an XCM message to be executed. /// The barriers one of which must be passed for an XCM message to be executed.
pub type Barrier = ( pub type Barrier = (
// Weight that is paid for may be consumed. // Weight that is paid for may be consumed.
TakeWeightCredit, 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. /// XCM weigher type.
pub type XcmWeigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>; pub type XcmWeigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
pub struct XcmConfig; pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig { impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall; type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter; type XcmSender = ();
type AssetTransactor = LocalAssetTransactor; type AssetTransactor = LocalAssetTransactor;
type OriginConverter = LocalOriginConverter; type OriginConverter = LocalOriginConverter;
type IsReserve = (); type IsReserve = ();
@@ -145,7 +136,7 @@ impl xcm_executor::Config for XcmConfig {
type PalletInstancesInfo = AllPalletsWithSystem; type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = ConstU32<64>; type MaxAssetsIntoHolding = ConstU32<64>;
type FeeManager = (); type FeeManager = ();
type MessageExporter = (); type MessageExporter = ToRialtoOrRialtoParachainSwitchExporter;
type UniversalAliases = Nothing; type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall; type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything; type SafeCallFilter = Everything;
@@ -160,7 +151,7 @@ pub type LocalOriginToLocation = (
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
parameter_types! { 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 { 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 // 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. // make `DescendOrigin` a bit more useful.
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>; type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmRouter = XcmRouter; type XcmRouter = ();
// Anyone can execute XCM messages locally. // Anyone can execute XCM messages locally.
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>; type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Everything; type XcmExecuteFilter = Everything;
@@ -197,70 +188,66 @@ impl pallet_xcm::Config for Runtime {
type ReachableDest = ReachableDest; type ReachableDest = ReachableDest;
} }
/// With-Rialto bridge. pub struct ToRialtoOrRialtoParachainSwitchExporter;
pub struct ToRialtoBridge;
impl XcmBridge for ToRialtoBridge { impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter {
type MessageBridge = WithRialtoMessageBridge; type Ticket = (NetworkId, (sp_std::prelude::Vec<u8>, XcmHash));
type MessageSender = pallet_bridge_messages::Pallet<Runtime, WithRialtoMessagesInstance>;
fn universal_location() -> InteriorMultiLocation { fn validate(
UniversalLocation::get() 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 { fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == RialtoNetwork::get()) let (network, ticket) = ticket;
} if network == RialtoNetwork::get() {
ToRialtoBlobExporter::deliver(ticket)
fn build_destination() -> MultiLocation { } else if network == RialtoParachainNetwork::get() {
let dest: InteriorMultiLocation = RialtoNetwork::get().into(); ToRialtoParachainBlobExporter::deliver(ticket)
let here = UniversalLocation::get(); } else {
dest.relative_to(&here) Err(SendError::Unroutable)
} }
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
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::rialto_messages::WeightCredit; use crate::{
rialto_messages::FromRialtoMessageDispatch,
rialto_parachain_messages::FromRialtoParachainMessageDispatch, DbWeight,
WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance,
};
use bp_messages::{ use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, 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 codec::Encode;
use pallet_bridge_messages::OutboundLanes;
use sp_core::Get;
use xcm_executor::XcmExecutor;
fn new_test_ext() -> sp_io::TestExternalities { fn new_test_ext() -> sp_io::TestExternalities {
sp_io::TestExternalities::new( 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] #[test]
fn xcm_messages_are_sent_using_bridge_router() { fn xcm_messages_to_rialto_are_sent_using_bridge_exporter() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); // ensure that the there are no messages queued
let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); assert_eq!(
let expected_hash = OutboundLanes::<Runtime, WithRialtoMessagesInstance>::get(
([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); crate::rialto_messages::XCM_LANE
)
.latest_generated_nonce,
0,
);
// message 1 to Rialto // export message instruction "sends" message to Rialto
let dest = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))); XcmExecutor::<XcmConfig>::execute_xcm_in_credit(
let send_result = send_xcm::<XcmRouter>(dest.into(), xcm.clone()); Here,
assert_eq!(send_result, Ok((expected_hash, expected_fee.clone()))); prepare_outbound_xcm_message(RialtoNetwork::get()),
Default::default(),
Weight::MAX,
Weight::MAX,
)
.ensure_complete()
.expect("runtime configuration must be correct");
// message 2 to RialtoParachain (expected hash is the same, since other lane is used) // ensure that the message has been queued
let dest = assert_eq!(
(Parent, X2(GlobalConsensus(RialtoNetwork::get()), Parachain(RIALTO_PARACHAIN_ID))); OutboundLanes::<Runtime, WithRialtoMessagesInstance>::get(
let send_result = send_xcm::<XcmRouter>(dest.into(), xcm); crate::rialto_messages::XCM_LANE
assert_eq!(send_result, Ok((expected_hash, expected_fee))); )
.latest_generated_nonce,
1,
);
}) })
} }
#[test]
fn xcm_messages_to_rialto_parachain_are_sent_using_bridge_exporter() {
new_test_ext().execute_with(|| {
// ensure that the there are no messages queued
assert_eq!(
OutboundLanes::<Runtime, WithRialtoParachainMessagesInstance>::get(
crate::rialto_parachain_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(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!(
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] #[test]
fn xcm_messages_from_rialto_are_dispatched() { fn xcm_messages_from_rialto_are_dispatched() {
type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>; let mut incoming_message = prepare_inbound_bridge_message();
type MessageDispatcher = FromBridgedChainMessageDispatch<
WithRialtoMessageBridge,
XcmExecutor,
XcmWeigher,
WeightCredit,
>;
new_test_ext().execute_with(|| { let dispatch_weight = FromRialtoMessageDispatch::dispatch_weight(&mut incoming_message);
let location: MultiLocation = assert_eq!(dispatch_weight, XcmRouterWeigher::<DbWeight>::get());
(Parent, X1(GlobalConsensus(RialtoNetwork::get()))).into();
let xcm: Xcm<RuntimeCall> = vec![Instruction::Trap(42)].into();
let mut incoming_message = DispatchMessage { // we care only about handing message to the XCM dispatcher, so we don't care about its
key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, // actual dispatch
data: DispatchMessageData { payload: Ok((location, xcm).into()) }, let dispatch_result =
}; FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message);
assert!(matches!(
dispatch_result.dispatch_level_result,
XcmBlobMessageDispatchResult::NotDispatched(_),
));
}
let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); #[test]
assert_eq!(dispatch_weight, BaseXcmWeight::get()); fn xcm_messages_from_rialto_parachain_are_dispatched() {
let mut incoming_message = prepare_inbound_bridge_message();
let dispatch_result = let dispatch_weight =
MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); FromRialtoParachainMessageDispatch::dispatch_weight(&mut incoming_message);
assert_eq!( assert_eq!(dispatch_weight, XcmRouterWeigher::<DbWeight>::get());
dispatch_result,
MessageDispatchResult { // we care only about handing message to the XCM dispatcher, so we don't care about its
unspent_weight: frame_support::weights::Weight::zero(), // actual dispatch
dispatch_level_result: (), let dispatch_result =
} FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message);
); assert!(matches!(
}) dispatch_result.dispatch_level_result,
XcmBlobMessageDispatchResult::NotDispatched(_),
));
} }
} }
@@ -111,6 +111,7 @@ std = [
"frame-support/std", "frame-support/std",
"frame-executive/std", "frame-executive/std",
"frame-system/std", "frame-system/std",
"frame-system-rpc-runtime-api/std",
"pallet-balances/std", "pallet-balances/std",
"pallet-bridge-grandpa/std", "pallet-bridge-grandpa/std",
"pallet-bridge-messages/std", "pallet-bridge-messages/std",
@@ -118,6 +119,7 @@ std = [
"pallet-timestamp/std", "pallet-timestamp/std",
"pallet-sudo/std", "pallet-sudo/std",
"pallet-transaction-payment/std", "pallet-transaction-payment/std",
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-xcm/std", "pallet-xcm/std",
"parachain-info/std", "parachain-info/std",
"polkadot-parachain/std", "polkadot-parachain/std",
+83 -96
View File
@@ -26,12 +26,7 @@
#[cfg(feature = "std")] #[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); 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;
use bridge_runtime_common::{
generate_bridge_reject_obsolete_headers_and_messages,
messages::source::{XcmBridge, XcmBridgeAdapter},
};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use cumulus_pallet_parachain_system::AnyRelayNumber; use cumulus_pallet_parachain_system::AnyRelayNumber;
use scale_info::TypeInfo; use scale_info::TypeInfo;
@@ -88,11 +83,10 @@ use pallet_xcm::XcmPassthrough;
use polkadot_parachain::primitives::Sibling; use polkadot_parachain::primitives::Sibling;
use xcm::latest::prelude::*; use xcm::latest::prelude::*;
use xcm_builder::{ use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset, NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
UsingComponents,
}; };
use xcm_executor::{Config, XcmExecutor}; use xcm_executor::{Config, XcmExecutor};
@@ -351,7 +345,7 @@ parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayLocation: MultiLocation = MultiLocation::parent();
pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id();
pub RelayOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); 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. /// The Millau network ID.
pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id();
/// The RialtoParachain 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. // the following constant must match the similar constant in the Millau runtime.
parameter_types! { parameter_types! {
/// The amount of weight an XCM operation takes. This is a safe overestimate. /// 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, 64 * 1024); pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 1024);
// One UNIT buys 1 second of weight. // One UNIT buys 1 second of weight.
pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT);
pub const MaxInstructions: u32 = 100; pub const MaxInstructions: u32 = 100;
@@ -428,12 +422,11 @@ match_types! {
}; };
} }
pub type Barrier = ( pub type Barrier = TakeWeightCredit;
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>, /// Dispatches received XCM messages from other chain.
AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>, pub type OnRialtoParachainBlobDispatcher =
// ^^^ Parent & its unit plurality gets free execution xcm_builder::BridgeBlobDispatcher<XcmRouter, UniversalLocation>;
);
/// XCM weigher type. /// XCM weigher type.
pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>; pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
@@ -441,7 +434,7 @@ pub type XcmWeigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstruct
pub struct XcmConfig; pub struct XcmConfig;
impl Config for XcmConfig { impl Config for XcmConfig {
type RuntimeCall = RuntimeCall; type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter; type XcmSender = ();
type AssetTransactor = LocalAssetTransactor; type AssetTransactor = LocalAssetTransactor;
type OriginConverter = XcmOriginToTransactDispatchOrigin; type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset; type IsReserve = NativeAsset;
@@ -459,7 +452,7 @@ impl Config for XcmConfig {
type AssetLocker = (); type AssetLocker = ();
type AssetExchanger = (); type AssetExchanger = ();
type FeeManager = (); type FeeManager = ();
type MessageExporter = (); type MessageExporter = millau_messages::ToMillauBlobExporter;
type UniversalAliases = Nothing; type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall; type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything; type SafeCallFilter = Everything;
@@ -468,42 +461,12 @@ impl Config for XcmConfig {
/// No local origins on this chain are allowed to dispatch XCM sends/executions. /// No local origins on this chain are allowed to dispatch XCM sends/executions.
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>; pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
/// The means for routing XCM messages which are not for local execution into the right message /// The XCM router. We are not sending messages to sibling/parent/child chains here.
/// queues. pub type XcmRouter = ();
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
}
}
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
parameter_types! { 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 { impl pallet_xcm::Config for Runtime {
@@ -875,17 +838,20 @@ cumulus_pallet_parachain_system::register_validate_block!(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::millau_messages::WeightCredit; use crate::millau_messages::{FromMillauMessageDispatch, XCM_LANE};
use bp_messages::{ use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
LaneId, MessageKey, LaneId, MessageKey,
}; };
use bp_runtime::messages::MessageDispatchResult;
use bridge_runtime_common::{ use bridge_runtime_common::{
integrity::check_additional_signed, messages::target::FromBridgedChainMessageDispatch, integrity::check_additional_signed,
messages_xcm_extension::{XcmBlobMessageDispatchResult, XcmRouterWeigher},
}; };
use codec::Encode; use codec::Encode;
use pallet_bridge_messages::OutboundLanes;
use sp_core::Get;
use sp_runtime::generic::Era; use sp_runtime::generic::Era;
use xcm_executor::XcmExecutor;
fn new_test_ext() -> sp_io::TestExternalities { fn new_test_ext() -> sp_io::TestExternalities {
sp_io::TestExternalities::new( sp_io::TestExternalities::new(
@@ -893,54 +859,75 @@ mod tests {
) )
} }
#[test] fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm<RuntimeCall> {
fn xcm_messages_to_millau_are_sent() { vec![ExportMessage {
new_test_ext().execute_with(|| { network: destination,
// the encoded message (origin ++ xcm) is 0x010109020419A8 destination: destination.into(),
let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); xcm: vec![Instruction::Trap(42)].into(),
let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); }]
.into()
}
let send_result = send_xcm::<XcmRouter>(dest.into(), xcm); #[test]
let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(1_000_000_u128))); fn xcm_messages_to_millau_are_sent_using_bridge_exporter() {
let expected_hash = new_test_ext().execute_with(|| {
([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); // ensure that the there are no messages queued
assert_eq!(send_result, Ok((expected_hash, expected_fee)),); 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] #[test]
fn xcm_messages_from_millau_are_dispatched() { 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(|| { new_test_ext().execute_with(|| {
let location: MultiLocation = let mut incoming_message = prepare_inbound_bridge_message();
(Parent, X1(GlobalConsensus(MillauNetwork::get()))).into();
let xcm: Xcm<RuntimeCall> = vec![Instruction::Trap(42)].into();
let mut incoming_message = DispatchMessage { let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message);
key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, assert_eq!(dispatch_weight, XcmRouterWeigher::<()>::get());
data: DispatchMessageData { payload: Ok((location, xcm).into()) },
};
let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message);
assert_eq!(dispatch_weight, UnitWeightCost::get());
// we care only about handing message to the XCM dispatcher, so we don't care about its
// actual dispatch
let dispatch_result = let dispatch_result =
MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message);
assert_eq!( assert!(matches!(
dispatch_result, dispatch_result.dispatch_level_result,
MessageDispatchResult { XcmBlobMessageDispatchResult::NotDispatched(_),
unspent_weight: frame_support::weights::Weight::zero(), ));
dispatch_level_result: (), });
}
);
})
} }
#[test] #[test]
@@ -19,14 +19,18 @@
// TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime.
// Should be extracted to a separate crate and reused here. // Should be extracted to a separate crate and reused here.
use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance};
use bp_messages::{LaneId, MessageNonce}; use bp_messages::LaneId;
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; use bridge_runtime_common::{
use bridge_runtime_common::messages::{ messages::{
self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge,
},
messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter},
}; };
use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; 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. /// Default lane that is used to send messages to Millau.
pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]);
@@ -51,15 +55,16 @@ pub type ToMillauMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>; messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
/// Message payload for Millau -> RialtoParachain messages. /// 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. /// Call-dispatch based message dispatch for Millau -> RialtoParachain messages.
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< pub type FromMillauMessageDispatch =
WithMillauMessageBridge, bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch<
xcm_executor::XcmExecutor<crate::XcmConfig>, bp_rialto_parachain::RialtoParachain,
crate::XcmWeigher, bp_millau::Millau,
WeightCredit, crate::OnRialtoParachainBlobDispatcher,
>; bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<()>,
>;
/// Messages proof for Millau -> RialtoParachain messages. /// Messages proof for Millau -> RialtoParachain messages.
pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>; pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>;
@@ -77,8 +82,6 @@ pub type ToMillauMaximalOutboundPayloadSize =
pub struct WithMillauMessageBridge; pub struct WithMillauMessageBridge;
impl MessageBridge for 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 = const BRIDGED_MESSAGES_PALLET_NAME: &'static str =
bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME;
@@ -97,16 +100,7 @@ impl messages::UnderlyingChainProvider for RialtoParachain {
} }
impl messages::ThisChainWithMessages for RialtoParachain { impl messages::ThisChainWithMessages for RialtoParachain {
type RuntimeCall = RuntimeCall;
type RuntimeOrigin = RuntimeOrigin; 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. /// Millau chain from message lane point of view.
@@ -121,8 +115,24 @@ impl messages::UnderlyingChainProvider for Millau {
type Chain = bp_millau::Millau; type Chain = bp_millau::Millau;
} }
impl messages::BridgedChainWithMessages for Millau { impl messages::BridgedChainWithMessages for Millau {}
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
true /// 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
} }
} }
@@ -16,14 +16,18 @@
//! Everything required to serve Millau <-> Rialto messages. //! Everything required to serve Millau <-> Rialto messages.
use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance};
use bp_messages::{LaneId, MessageNonce}; use bp_messages::LaneId;
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::{
use bridge_runtime_common::messages::{ messages::{
self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge,
},
messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter},
}; };
use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug};
use xcm::latest::prelude::*;
use xcm_builder::HaulBlobExporter;
/// Lane that is used for XCM messages exchange. /// Lane that is used for XCM messages exchange.
pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]);
@@ -48,15 +52,16 @@ pub type ToMillauMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>; messages::source::FromThisChainMessageVerifier<WithMillauMessageBridge>;
/// Message payload for Millau -> Rialto messages. /// 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. /// Call-dispatch based message dispatch for Millau -> Rialto messages.
pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< pub type FromMillauMessageDispatch =
WithMillauMessageBridge, bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch<
xcm_executor::XcmExecutor<crate::xcm_config::XcmConfig>, bp_rialto::Rialto,
crate::xcm_config::XcmWeigher, bp_millau::Millau,
WeightCredit, crate::xcm_config::OnRialtoBlobDispatcher,
>; bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<crate::DbWeight>,
>;
/// Messages proof for Millau -> Rialto messages. /// Messages proof for Millau -> Rialto messages.
pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>; pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof<bp_millau::Hash>;
@@ -74,8 +79,6 @@ pub type ToMillauMaximalOutboundPayloadSize =
pub struct WithMillauMessageBridge; pub struct WithMillauMessageBridge;
impl MessageBridge for 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; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME;
type ThisChain = Rialto; type ThisChain = Rialto;
@@ -94,15 +97,6 @@ impl messages::UnderlyingChainProvider for Rialto {
impl messages::ThisChainWithMessages for Rialto { impl messages::ThisChainWithMessages for Rialto {
type RuntimeOrigin = RuntimeOrigin; 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. /// Millau chain from message lane point of view.
@@ -117,9 +111,29 @@ impl messages::UnderlyingChainProvider for Millau {
type Chain = bp_millau::Millau; type Chain = bp_millau::Millau;
} }
impl messages::BridgedChainWithMessages for Millau { impl messages::BridgedChainWithMessages for Millau {}
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
true /// 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
} }
} }
+86 -91
View File
@@ -17,14 +17,11 @@
//! XCM configurations for the Rialto runtime. //! XCM configurations for the Rialto runtime.
use super::{ use super::{
millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, Runtime, millau_messages::ToMillauBlobExporter, AccountId, AllPalletsWithSystem, Balances, Runtime,
RuntimeCall, RuntimeEvent, RuntimeOrigin, WithMillauMessagesInstance, XcmPallet, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet,
}; };
use bp_rialto::WeightToFee; use bp_rialto::WeightToFee;
use bridge_runtime_common::{ use bridge_runtime_common::CustomNetworkId;
messages::source::{XcmBridge, XcmBridgeAdapter},
CustomNetworkId,
};
use frame_support::{ use frame_support::{
parameter_types, parameter_types,
traits::{ConstU32, Everything, Nothing}, traits::{ConstU32, Everything, Nothing},
@@ -32,9 +29,9 @@ use frame_support::{
}; };
use xcm::latest::prelude::*; use xcm::latest::prelude::*;
use xcm_builder::{ use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation,
CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, UsingComponents,
}; };
parameter_types! { parameter_types! {
@@ -95,30 +92,28 @@ parameter_types! {
pub const MaxInstructions: u32 = 100; 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 /// The XCM router. We are not sending messages to sibling/parent/child chains here.
/// individual routers. pub type XcmRouter = ();
pub type XcmRouter = (
// Router to send messages to Millau.
XcmBridgeAdapter<ToMillauBridge>,
);
/// The barriers one of which must be passed for an XCM message to be executed. /// The barriers one of which must be passed for an XCM message to be executed.
pub type Barrier = ( pub type Barrier = (
// Weight that is paid for may be consumed. // Weight that is paid for may be consumed.
TakeWeightCredit, 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. /// Incoming XCM weigher type.
pub type XcmWeigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>; pub type XcmWeigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
pub struct XcmConfig; pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig { impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall; type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter; type XcmSender = ();
type AssetTransactor = LocalAssetTransactor; type AssetTransactor = LocalAssetTransactor;
type OriginConverter = LocalOriginConverter; type OriginConverter = LocalOriginConverter;
type IsReserve = (); type IsReserve = ();
@@ -137,7 +132,7 @@ impl xcm_executor::Config for XcmConfig {
type PalletInstancesInfo = AllPalletsWithSystem; type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = ConstU32<64>; type MaxAssetsIntoHolding = ConstU32<64>;
type FeeManager = (); type FeeManager = ();
type MessageExporter = (); type MessageExporter = ToMillauBlobExporter;
type UniversalAliases = Nothing; type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall; type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything; type SafeCallFilter = Everything;
@@ -152,7 +147,7 @@ pub type LocalOriginToLocation = (
#[cfg(feature = "runtime-benchmarks")] #[cfg(feature = "runtime-benchmarks")]
parameter_types! { 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 { impl pallet_xcm::Config for Runtime {
@@ -189,43 +184,24 @@ impl pallet_xcm::Config for Runtime {
type ReachableDest = ReachableDest; 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::millau_messages::WeightCredit; use crate::{
millau_messages::{FromMillauMessageDispatch, XCM_LANE},
DbWeight, WithMillauMessagesInstance,
};
use bp_messages::{ use bp_messages::{
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
LaneId, MessageKey, LaneId, MessageKey,
}; };
use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::messages_xcm_extension::{
use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; XcmBlobMessageDispatchResult, XcmRouterWeigher,
};
use codec::Encode; use codec::Encode;
use pallet_bridge_messages::OutboundLanes;
use sp_core::Get;
use xcm_executor::XcmExecutor;
fn new_test_ext() -> sp_io::TestExternalities { fn new_test_ext() -> sp_io::TestExternalities {
sp_io::TestExternalities::new( sp_io::TestExternalities::new(
@@ -233,53 +209,72 @@ mod tests {
) )
} }
#[test] fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm<RuntimeCall> {
fn xcm_messages_to_millau_are_sent() { vec![ExportMessage {
new_test_ext().execute_with(|| { network: destination,
// the encoded message (origin ++ xcm) is 0x010109030419A8 destination: destination.into(),
let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); xcm: vec![Instruction::Trap(42)].into(),
let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); }]
.into()
}
let send_result = send_xcm::<XcmRouter>(dest.into(), xcm); #[test]
let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); fn xcm_messages_to_millau_are_sent_using_bridge_exporter() {
let expected_hash = new_test_ext().execute_with(|| {
([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); // ensure that the there are no messages queued
assert_eq!(send_result, Ok((expected_hash, expected_fee)),); 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] #[test]
fn xcm_messages_from_millau_are_dispatched() { fn xcm_messages_from_millau_are_dispatched() {
type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>; let mut incoming_message = prepare_inbound_bridge_message();
type MessageDispatcher = FromBridgedChainMessageDispatch<
WithMillauMessageBridge,
XcmExecutor,
XcmWeigher,
WeightCredit,
>;
new_test_ext().execute_with(|| { let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message);
let location: MultiLocation = assert_eq!(dispatch_weight, XcmRouterWeigher::<DbWeight>::get());
(Parent, X1(GlobalConsensus(MillauNetwork::get()))).into();
let xcm: Xcm<RuntimeCall> = vec![Instruction::Trap(42)].into();
let mut incoming_message = DispatchMessage { // we care only about handing message to the XCM dispatcher, so we don't care about its
key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, // actual dispatch
data: DispatchMessageData { payload: Ok((location, xcm).into()) }, let dispatch_result =
}; FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message);
assert!(matches!(
let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); dispatch_result.dispatch_level_result,
assert_eq!(dispatch_weight, BaseXcmWeight::get()); XcmBlobMessageDispatchResult::NotDispatched(_),
));
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: (),
}
);
})
} }
} }
+1 -1
View File
@@ -83,7 +83,7 @@ macro_rules! assert_bridge_messages_pallet_types(
use $crate::messages::{ use $crate::messages::{
source::{FromThisChainMessagePayload, TargetHeaderChainAdapter}, source::{FromThisChainMessagePayload, TargetHeaderChainAdapter},
target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter}, target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter},
AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, AccountIdOf, BalanceOf, BridgedChain, ThisChain,
}; };
use pallet_bridge_messages::Config as MessagesConfig; use pallet_bridge_messages::Config as MessagesConfig;
use static_assertions::assert_type_eq_all; use static_assertions::assert_type_eq_all;
+23 -332
View File
@@ -25,28 +25,18 @@ pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider};
use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_header_chain::{HeaderChain, HeaderChainError};
use bp_messages::{ use bp_messages::{
source_chain::{LaneMessageVerifier, TargetHeaderChain}, source_chain::{LaneMessageVerifier, TargetHeaderChain},
target_chain::{ target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain,
},
InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData,
}; };
use bp_runtime::{ use bp_runtime::{Chain, RawStorageProof, Size, StorageProofChecker, StorageProofError};
messages::MessageDispatchResult, Chain, ChainId, RawStorageProof, Size, StorageProofChecker, use codec::{Decode, Encode};
StorageProofError,
};
use codec::{Decode, DecodeLimit, Encode};
use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug};
use hash_db::Hasher; use hash_db::Hasher;
use scale_info::TypeInfo; use scale_info::TypeInfo;
use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec};
use xcm::latest::prelude::*;
/// Bidirectional message bridge. /// Bidirectional message bridge.
pub trait MessageBridge { 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. /// Name of the paired messages pallet instance at the Bridged chain.
/// ///
/// Should be the name that is used in the `construct_runtime!()` macro. /// Should be the name that is used in the `construct_runtime!()` macro.
@@ -64,24 +54,10 @@ pub trait MessageBridge {
pub trait ThisChainWithMessages: UnderlyingChainProvider { pub trait ThisChainWithMessages: UnderlyingChainProvider {
/// Call origin on the chain. /// Call origin on the chain.
type RuntimeOrigin; 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. /// Bridged chain that has `pallet-bridge-messages` module.
pub trait BridgedChainWithMessages: UnderlyingChainProvider { 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;
}
/// This chain in context of message bridge. /// This chain in context of message bridge.
pub type ThisChain<B> = <B as MessageBridge>::ThisChain; 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>>; pub type BalanceOf<C> = bp_runtime::BalanceOf<UnderlyingChainOf<C>>;
/// Type of origin that is used on the chain. /// Type of origin that is used on the chain.
pub type OriginOf<C> = <C as ThisChainWithMessages>::RuntimeOrigin; 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. /// Error that happens during message verification.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@@ -128,7 +102,7 @@ pub mod source {
use super::*; use super::*;
/// Message payload for This -> Bridged chain messages. /// 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. /// Maximal size of outbound message payload.
pub struct FromThisChainMaximalOutboundPayloadSize<B>(PhantomData<B>); pub struct FromThisChainMaximalOutboundPayloadSize<B>(PhantomData<B>);
@@ -186,13 +160,6 @@ pub mod source {
#[derive(RuntimeDebug)] #[derive(RuntimeDebug)]
pub struct FromThisChainMessageVerifier<B>(PhantomData<B>); 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> impl<B> LaneMessageVerifier<OriginOf<ThisChain<B>>, FromThisChainMessagePayload>
for FromThisChainMessageVerifier<B> for FromThisChainMessageVerifier<B>
where where
@@ -205,24 +172,16 @@ pub mod source {
type Error = &'static str; type Error = &'static str;
fn verify_message( fn verify_message(
submitter: &OriginOf<ThisChain<B>>, _submitter: &OriginOf<ThisChain<B>>,
lane: &LaneId, _lane: &LaneId,
lane_outbound_data: &OutboundLaneData, _lane_outbound_data: &OutboundLaneData,
_payload: &FromThisChainMessagePayload, _payload: &FromThisChainMessagePayload,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
// reject message if lane is blocked // IMPORTANT: any error that is returned here is fatal for the bridge, because
if !ThisChain::<B>::is_message_accepted(submitter, lane) { // this code is executed at the bridge hub and message sender actually lives
return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE) // 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).
// 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)
}
Ok(()) Ok(())
} }
@@ -263,9 +222,15 @@ pub mod source {
pub fn verify_chain_message<B: MessageBridge>( pub fn verify_chain_message<B: MessageBridge>(
payload: &FromThisChainMessagePayload, payload: &FromThisChainMessagePayload,
) -> Result<(), Error> { ) -> Result<(), Error> {
if !BridgedChain::<B>::verify_dispatch_weight(payload) { // IMPORTANT: any error that is returned here is fatal for the bridge, because
return Err(Error::InvalidMessageWeight) // 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 // The maximal size of extrinsic at Substrate-based chain depends on the
// `frame_system::Config::MaximumBlockLength` and // `frame_system::Config::MaximumBlockLength` and
@@ -316,92 +281,6 @@ pub mod source {
) )
.map_err(Error::HeaderChain)? .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. /// Sub-module that is declaring types required for processing Bridged -> This chain messages.
@@ -409,35 +288,7 @@ pub mod target {
use super::*; use super::*;
/// Decoded Bridged -> This message payload. /// Decoded Bridged -> This message payload.
#[derive(RuntimeDebug, PartialEq, Eq)] pub type FromBridgedChainMessagePayload = crate::messages_xcm_extension::XcmAsPlainPayload;
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 }
}
}
/// Messages proof from bridged chain: /// 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. /// Return maximal dispatch weight of the message we're able to receive.
pub fn maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { pub fn maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight {
maximal_extrinsic_weight / 2 maximal_extrinsic_weight / 2
@@ -745,54 +484,6 @@ mod tests {
use sp_core::H256; use sp_core::H256;
use sp_runtime::traits::Header as _; 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(),
&regular_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()
},
&regular_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] #[test]
fn verify_chain_message_rejects_message_with_too_large_declared_weight() { fn verify_chain_message_rejects_message_with_too_large_declared_weight() {
assert!(source::verify_chain_message::<OnThisChainBridge>(&vec![ assert!(source::verify_chain_message::<OnThisChainBridge>(&vec![
@@ -28,13 +28,43 @@ use bp_messages::{
}; };
use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain};
use codec::{Decode, Encode}; 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 scale_info::TypeInfo;
use sp_std::marker::PhantomData;
use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; 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<u8>; 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 /// Message dispatch result type for single message
#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
pub enum XcmBlobMessageDispatchResult { pub enum XcmBlobMessageDispatchResult {
+5 -41
View File
@@ -33,7 +33,7 @@ use crate::messages::{
}; };
use bp_header_chain::{ChainWithGrandpa, HeaderChain}; 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_parachains::SingleParaStoredHeaderDataBuilder;
use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
@@ -87,10 +87,6 @@ pub type BridgedChainHeader =
pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]);
/// Bridged chain id used in tests. /// Bridged chain id used in tests.
pub const TEST_BRIDGED_CHAIN_ID: ChainId = *b"brdg"; 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`. /// Maximal extrinsic weight at the `BridgedChain`.
pub const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; pub const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048;
/// Maximal extrinsic size at the `BridgedChain`. /// Maximal extrinsic size at the `BridgedChain`.
@@ -222,7 +218,7 @@ impl pallet_bridge_messages::Config for TestRuntime {
type MaximalOutboundPayloadSize = FromThisChainMaximalOutboundPayloadSize<OnThisChainBridge>; type MaximalOutboundPayloadSize = FromThisChainMaximalOutboundPayloadSize<OnThisChainBridge>;
type OutboundPayload = FromThisChainMessagePayload; type OutboundPayload = FromThisChainMessagePayload;
type InboundPayload = FromBridgedChainMessagePayload<ThisChainRuntimeCall>; type InboundPayload = FromBridgedChainMessagePayload;
type InboundRelayer = BridgedChainAccountId; type InboundRelayer = BridgedChainAccountId;
type DeliveryPayments = (); type DeliveryPayments = ();
@@ -235,8 +231,7 @@ impl pallet_bridge_messages::Config for TestRuntime {
>; >;
type SourceHeaderChain = SourceHeaderChainAdapter<OnThisChainBridge>; type SourceHeaderChain = SourceHeaderChainAdapter<OnThisChainBridge>;
type MessageDispatch = type MessageDispatch = ForbidInboundMessages<(), FromBridgedChainMessagePayload>;
ForbidInboundMessages<(), FromBridgedChainMessagePayload<ThisChainRuntimeCall>>;
type BridgedChainId = BridgedChainId; type BridgedChainId = BridgedChainId;
} }
@@ -253,8 +248,6 @@ impl pallet_bridge_relayers::Config for TestRuntime {
pub struct OnThisChainBridge; pub struct OnThisChainBridge;
impl MessageBridge for 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 = ""; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
type ThisChain = ThisChain; type ThisChain = ThisChain;
@@ -268,8 +261,6 @@ impl MessageBridge for OnThisChainBridge {
pub struct OnBridgedChainBridge; pub struct OnBridgedChainBridge;
impl MessageBridge for 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 = ""; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
type ThisChain = BridgedChain; type ThisChain = BridgedChain;
@@ -331,22 +322,9 @@ impl UnderlyingChainProvider for ThisChain {
impl ThisChainWithMessages for ThisChain { impl ThisChainWithMessages for ThisChain {
type RuntimeOrigin = ThisChainCallOrigin; 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 { impl BridgedChainWithMessages for ThisChain {}
fn verify_dispatch_weight(_message_payload: &[u8]) -> bool {
unreachable!()
}
}
/// Underlying chain of `BridgedChain`. /// Underlying chain of `BridgedChain`.
pub struct BridgedUnderlyingChain; pub struct BridgedUnderlyingChain;
@@ -413,20 +391,6 @@ impl UnderlyingChainProvider for BridgedChain {
impl ThisChainWithMessages for BridgedChain { impl ThisChainWithMessages for BridgedChain {
type RuntimeOrigin = BridgedChainOrigin; 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 { 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
}
}
+2 -2
View File
@@ -502,11 +502,11 @@ pub struct StrippableError<T> {
} }
impl<T: Debug> From<T> for StrippableError<T> { impl<T: Debug> From<T> for StrippableError<T> {
fn from(err: T) -> Self { fn from(_err: T) -> Self {
Self { Self {
_phantom_data: Default::default(), _phantom_data: Default::default(),
#[cfg(feature = "std")] #[cfg(feature = "std")]
message: format!("{:?}", err), message: format!("{:?}", _err),
} }
} }
} }
@@ -16,37 +16,18 @@
//! Millau chain specification for CLI. //! Millau chain specification for CLI.
use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use crate::cli::{encode_message::CliEncodeMessage, CliChain};
use bp_rialto_parachain::RIALTO_PARACHAIN_ID;
use bp_runtime::EncodedOrDecodedCall; use bp_runtime::EncodedOrDecodedCall;
use relay_millau_client::Millau; use relay_millau_client::Millau;
use relay_substrate_client::SimpleRuntimeVersion; use relay_substrate_client::SimpleRuntimeVersion;
use xcm::latest::prelude::*;
impl CliEncodeMessage for Millau { impl CliEncodeMessage for Millau {
fn encode_send_xcm( fn encode_execute_xcm(
message: xcm::VersionedXcm<()>, message: xcm::VersionedXcm<Self::Call>,
bridge_instance_index: u8,
) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> { ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> {
let dest = match bridge_instance_index { Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::execute {
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()),
message: Box::new(message), message: Box::new(message),
max_weight: Self::estimate_execute_xcm_weight(),
}) })
.into()) .into())
} }
@@ -16,29 +16,18 @@
//! Rialto chain specification for CLI. //! 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 bp_runtime::EncodedOrDecodedCall;
use relay_rialto_client::Rialto; use relay_rialto_client::Rialto;
use relay_substrate_client::SimpleRuntimeVersion; use relay_substrate_client::SimpleRuntimeVersion;
use xcm::latest::prelude::*;
impl CliEncodeMessage for Rialto { impl CliEncodeMessage for Rialto {
fn encode_send_xcm( fn encode_execute_xcm(
message: xcm::VersionedXcm<()>, message: xcm::VersionedXcm<Self::Call>,
bridge_instance_index: u8,
) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> { ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> {
let dest = match bridge_instance_index { Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::execute {
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()),
message: Box::new(message), message: Box::new(message),
max_weight: Self::estimate_execute_xcm_weight(),
}) })
.into()) .into())
} }
@@ -16,33 +16,21 @@
//! Rialto parachain specification for CLI. //! 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 bp_runtime::EncodedOrDecodedCall;
use bridge_runtime_common::CustomNetworkId;
use relay_rialto_parachain_client::RialtoParachain; use relay_rialto_parachain_client::RialtoParachain;
use relay_substrate_client::SimpleRuntimeVersion; use relay_substrate_client::SimpleRuntimeVersion;
use xcm::latest::prelude::*;
impl CliEncodeMessage for RialtoParachain { impl CliEncodeMessage for RialtoParachain {
fn encode_send_xcm( fn encode_execute_xcm(
message: xcm::VersionedXcm<()>, message: xcm::VersionedXcm<Self::Call>,
bridge_instance_index: u8,
) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> { ) -> anyhow::Result<EncodedOrDecodedCall<Self::Call>> {
type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; type RuntimeCall = relay_rialto_parachain_client::RuntimeCall;
type XcmCall = relay_rialto_parachain_client::runtime_types::pallet_xcm::pallet::Call; type XcmCall = relay_rialto_parachain_client::runtime_types::pallet_xcm::pallet::Call;
let dest = match bridge_instance_index { let xcm_call = XcmCall::execute {
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)) }),
message: Box::new(unsafe { std::mem::transmute(message) }), message: Box::new(unsafe { std::mem::transmute(message) }),
max_weight: Self::estimate_execute_xcm_weight(),
}; };
Ok(RuntimeCall::PolkadotXcm(xcm_call).into()) Ok(RuntimeCall::PolkadotXcm(xcm_call).into())
@@ -37,28 +37,6 @@ pub enum FullBridge {
BridgeHubPolkadotToBridgeHubKusama, 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. /// Minimal bridge representation that can be used from the CLI.
/// It connects a source chain to a target chain. /// It connects a source chain to a target chain.
pub trait CliBridgeBase: Sized { pub trait CliBridgeBase: Sized {
@@ -17,6 +17,7 @@
use crate::cli::{ExplicitOrMaximal, HexBytes}; use crate::cli::{ExplicitOrMaximal, HexBytes};
use bp_runtime::EncodedOrDecodedCall; use bp_runtime::EncodedOrDecodedCall;
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight;
use relay_substrate_client::Chain; use relay_substrate_client::Chain;
use structopt::StructOpt; use structopt::StructOpt;
@@ -42,11 +43,16 @@ pub enum Message {
pub type RawMessage = Vec<u8>; pub type RawMessage = Vec<u8>;
pub trait CliEncodeMessage: Chain { pub trait CliEncodeMessage: Chain {
/// Encode a send XCM call of the XCM pallet. /// Encode an `execute` XCM call of the XCM pallet.
fn encode_send_xcm( fn encode_execute_xcm(
message: xcm::VersionedXcm<()>, message: xcm::VersionedXcm<Self::Call>,
bridge_instance_index: u8,
) -> anyhow::Result<EncodedOrDecodedCall<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. /// Encode message payload passed through CLI flags.
@@ -125,7 +131,7 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!(msg.len(), 100); assert_eq!(msg.len(), 100);
// check that it decodes to valid xcm // check that it decodes to valid xcm
let _ = decode_xcm(msg).unwrap(); let _ = decode_xcm::<()>(msg).unwrap();
} }
#[test] #[test]
@@ -140,6 +146,6 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!(msg.len(), maximal_size as usize); assert_eq!(msg.len(), maximal_size as usize);
// check that it decodes to valid xcm // check that it decodes to valid xcm
let _ = decode_xcm(msg).unwrap(); let _ = decode_xcm::<()>(msg).unwrap();
} }
} }
@@ -75,10 +75,7 @@ where
let source_sign = data.source_sign.to_keypair::<Self::Source>()?; let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
let payload_len = payload.encoded_size(); let payload_len = payload.encoded_size();
let send_message_call = Self::Source::encode_send_xcm( let send_message_call = Self::Source::encode_execute_xcm(decode_xcm(payload)?)?;
decode_xcm(payload)?,
data.bridge.bridge_instance_index(),
)?;
source_client source_client
.submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| { .submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| {
@@ -130,7 +127,7 @@ impl SendMessage {
} }
/// Decode SCALE encoded raw XCM message. /// 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[..]) Decode::decode(&mut &message[..])
.map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e)) .map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e))
} }