mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 11:01:01 +00:00
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:
committed by
Bastian Köcher
parent
2407228972
commit
a75c28d5b2
+5
-4
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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: (),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(),
|
|
||||||
®ular_outbound_message_payload(),
|
|
||||||
),
|
|
||||||
Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() {
|
|
||||||
assert_eq!(
|
|
||||||
source::FromThisChainMessageVerifier::<OnThisChainBridge>::verify_message(
|
|
||||||
&frame_system::RawOrigin::Root.into(),
|
|
||||||
&TEST_LANE_ID,
|
|
||||||
&OutboundLaneData {
|
|
||||||
latest_received_nonce: 100,
|
|
||||||
latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
®ular_outbound_message_payload(),
|
|
||||||
),
|
|
||||||
Err(source::TOO_MANY_PENDING_MESSAGES)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn verify_chain_message_rejects_message_with_too_small_declared_weight() {
|
|
||||||
assert!(source::verify_chain_message::<OnThisChainBridge>(&vec![
|
|
||||||
42;
|
|
||||||
BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT -
|
|
||||||
1
|
|
||||||
])
|
|
||||||
.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[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 {
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user