mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 17:11:02 +00:00
Bridges subtree update (#2602)
## Summary This PR aligns Rococo/Westend bridge with latest Bridges repo development: - https://github.com/paritytech/parity-bridges-common/pull/2727 - https://github.com/paritytech/parity-bridges-common/pull/2728 - https://github.com/paritytech/parity-bridges-common/pull/2729 Part of: https://github.com/paritytech/parity-bridges-common/issues/2452
This commit is contained in:
Generated
+36
@@ -1817,6 +1817,13 @@ dependencies = [
|
|||||||
"sp-std 8.0.0",
|
"sp-std 8.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bp-xcm-bridge-hub"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"sp-std 8.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bp-xcm-bridge-hub-router"
|
name = "bp-xcm-bridge-hub-router"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -1915,6 +1922,7 @@ dependencies = [
|
|||||||
"pallet-utility",
|
"pallet-utility",
|
||||||
"pallet-xcm",
|
"pallet-xcm",
|
||||||
"pallet-xcm-benchmarks",
|
"pallet-xcm-benchmarks",
|
||||||
|
"pallet-xcm-bridge-hub",
|
||||||
"parachains-common",
|
"parachains-common",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"polkadot-core-primitives",
|
"polkadot-core-primitives",
|
||||||
@@ -2032,6 +2040,7 @@ dependencies = [
|
|||||||
name = "bridge-hub-westend-runtime"
|
name = "bridge-hub-westend-runtime"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bp-asset-hub-rococo",
|
||||||
"bp-asset-hub-westend",
|
"bp-asset-hub-westend",
|
||||||
"bp-bridge-hub-rococo",
|
"bp-bridge-hub-rococo",
|
||||||
"bp-bridge-hub-westend",
|
"bp-bridge-hub-westend",
|
||||||
@@ -2078,6 +2087,7 @@ dependencies = [
|
|||||||
"pallet-utility",
|
"pallet-utility",
|
||||||
"pallet-xcm",
|
"pallet-xcm",
|
||||||
"pallet-xcm-benchmarks",
|
"pallet-xcm-benchmarks",
|
||||||
|
"pallet-xcm-bridge-hub",
|
||||||
"parachains-common",
|
"parachains-common",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"polkadot-core-primitives",
|
"polkadot-core-primitives",
|
||||||
@@ -2121,6 +2131,7 @@ dependencies = [
|
|||||||
"bp-relayers",
|
"bp-relayers",
|
||||||
"bp-runtime",
|
"bp-runtime",
|
||||||
"bp-test-utils",
|
"bp-test-utils",
|
||||||
|
"bp-xcm-bridge-hub",
|
||||||
"bp-xcm-bridge-hub-router",
|
"bp-xcm-bridge-hub-router",
|
||||||
"frame-support",
|
"frame-support",
|
||||||
"frame-system",
|
"frame-system",
|
||||||
@@ -11072,6 +11083,31 @@ dependencies = [
|
|||||||
"staging-xcm-executor",
|
"staging-xcm-executor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pallet-xcm-bridge-hub"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bp-header-chain",
|
||||||
|
"bp-messages",
|
||||||
|
"bp-runtime",
|
||||||
|
"bp-xcm-bridge-hub",
|
||||||
|
"bridge-runtime-common",
|
||||||
|
"frame-support",
|
||||||
|
"frame-system",
|
||||||
|
"log",
|
||||||
|
"pallet-balances",
|
||||||
|
"pallet-bridge-messages",
|
||||||
|
"parity-scale-codec",
|
||||||
|
"scale-info",
|
||||||
|
"sp-core",
|
||||||
|
"sp-io",
|
||||||
|
"sp-runtime",
|
||||||
|
"sp-std 8.0.0",
|
||||||
|
"staging-xcm",
|
||||||
|
"staging-xcm-builder",
|
||||||
|
"staging-xcm-executor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pallet-xcm-bridge-hub-router"
|
name = "pallet-xcm-bridge-hub-router"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ members = [
|
|||||||
"bridges/modules/messages",
|
"bridges/modules/messages",
|
||||||
"bridges/modules/parachains",
|
"bridges/modules/parachains",
|
||||||
"bridges/modules/relayers",
|
"bridges/modules/relayers",
|
||||||
|
"bridges/modules/xcm-bridge-hub",
|
||||||
"bridges/modules/xcm-bridge-hub-router",
|
"bridges/modules/xcm-bridge-hub-router",
|
||||||
"bridges/primitives/chain-asset-hub-rococo",
|
"bridges/primitives/chain-asset-hub-rococo",
|
||||||
"bridges/primitives/chain-asset-hub-westend",
|
"bridges/primitives/chain-asset-hub-westend",
|
||||||
@@ -33,6 +34,7 @@ members = [
|
|||||||
"bridges/primitives/relayers",
|
"bridges/primitives/relayers",
|
||||||
"bridges/primitives/runtime",
|
"bridges/primitives/runtime",
|
||||||
"bridges/primitives/test-utils",
|
"bridges/primitives/test-utils",
|
||||||
|
"bridges/primitives/xcm-bridge-hub",
|
||||||
"bridges/primitives/xcm-bridge-hub-router",
|
"bridges/primitives/xcm-bridge-hub-router",
|
||||||
"cumulus/client/cli",
|
"cumulus/client/cli",
|
||||||
"cumulus/client/collator",
|
"cumulus/client/collator",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ bp-parachains = { path = "../../primitives/parachains", default-features = false
|
|||||||
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
|
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
|
||||||
bp-relayers = { path = "../../primitives/relayers", default-features = false }
|
bp-relayers = { path = "../../primitives/relayers", default-features = false }
|
||||||
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
||||||
|
bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false }
|
||||||
bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false }
|
bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false }
|
||||||
pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false }
|
pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false }
|
||||||
pallet-bridge-messages = { path = "../../modules/messages", default-features = false }
|
pallet-bridge-messages = { path = "../../modules/messages", default-features = false }
|
||||||
@@ -59,6 +60,7 @@ std = [
|
|||||||
"bp-relayers/std",
|
"bp-relayers/std",
|
||||||
"bp-runtime/std",
|
"bp-runtime/std",
|
||||||
"bp-xcm-bridge-hub-router/std",
|
"bp-xcm-bridge-hub-router/std",
|
||||||
|
"bp-xcm-bridge-hub/std",
|
||||||
"codec/std",
|
"codec/std",
|
||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"frame-system/std",
|
"frame-system/std",
|
||||||
|
|||||||
@@ -22,26 +22,23 @@
|
|||||||
//! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue`
|
//! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue`
|
||||||
|
|
||||||
use bp_messages::{
|
use bp_messages::{
|
||||||
source_chain::{MessagesBridge, OnMessagesDelivered},
|
source_chain::OnMessagesDelivered,
|
||||||
target_chain::{DispatchMessage, MessageDispatch},
|
target_chain::{DispatchMessage, MessageDispatch},
|
||||||
LaneId, MessageNonce,
|
LaneId, MessageNonce,
|
||||||
};
|
};
|
||||||
use bp_runtime::messages::MessageDispatchResult;
|
use bp_runtime::messages::MessageDispatchResult;
|
||||||
|
pub use bp_xcm_bridge_hub::XcmAsPlainPayload;
|
||||||
use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
|
use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::{traits::Get, weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound};
|
use frame_support::{traits::Get, weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound};
|
||||||
use pallet_bridge_messages::{
|
use pallet_bridge_messages::{
|
||||||
Config as MessagesConfig, OutboundLanesCongestedSignals, Pallet as MessagesPallet,
|
Config as MessagesConfig, OutboundLanesCongestedSignals, WeightInfoExt as MessagesPalletWeights,
|
||||||
WeightInfoExt as MessagesPalletWeights,
|
|
||||||
};
|
};
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
use sp_runtime::SaturatedConversion;
|
use sp_runtime::SaturatedConversion;
|
||||||
use sp_std::{fmt::Debug, marker::PhantomData};
|
use sp_std::{fmt::Debug, marker::PhantomData};
|
||||||
use xcm::prelude::*;
|
use xcm::prelude::*;
|
||||||
use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError};
|
use xcm_builder::{DispatchBlob, DispatchBlobError};
|
||||||
|
|
||||||
/// Plain "XCM" payload, which we transfer through bridge
|
|
||||||
pub type XcmAsPlainPayload = sp_std::prelude::Vec<u8>;
|
|
||||||
|
|
||||||
/// 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)]
|
||||||
@@ -123,6 +120,7 @@ impl<
|
|||||||
|
|
||||||
/// A pair of sending chain location and message lane, used by this chain to send messages
|
/// A pair of sending chain location and message lane, used by this chain to send messages
|
||||||
/// over the bridge.
|
/// over the bridge.
|
||||||
|
#[cfg_attr(feature = "std", derive(Debug, Eq, PartialEq))]
|
||||||
pub struct SenderAndLane {
|
pub struct SenderAndLane {
|
||||||
/// Sending chain relative location.
|
/// Sending chain relative location.
|
||||||
pub location: MultiLocation,
|
pub location: MultiLocation,
|
||||||
@@ -144,8 +142,6 @@ pub trait XcmBlobHauler {
|
|||||||
type Runtime: MessagesConfig<Self::MessagesInstance>;
|
type Runtime: MessagesConfig<Self::MessagesInstance>;
|
||||||
/// Instance of the messages pallet that is used to send messages.
|
/// Instance of the messages pallet that is used to send messages.
|
||||||
type MessagesInstance: 'static;
|
type MessagesInstance: 'static;
|
||||||
/// Returns lane used by this hauler.
|
|
||||||
type SenderAndLane: Get<SenderAndLane>;
|
|
||||||
|
|
||||||
/// Actual XCM message sender (`HRMP` or `UMP`) to the source chain
|
/// Actual XCM message sender (`HRMP` or `UMP`) to the source chain
|
||||||
/// location (`Self::SenderAndLane::get().location`).
|
/// location (`Self::SenderAndLane::get().location`).
|
||||||
@@ -166,54 +162,25 @@ pub trait XcmBlobHauler {
|
|||||||
/// makes sure that XCM blob is sent to the outbound lane to be relayed.
|
/// makes sure that XCM blob is sent to the outbound lane to be relayed.
|
||||||
///
|
///
|
||||||
/// It needs to be used at the source bridge hub.
|
/// It needs to be used at the source bridge hub.
|
||||||
pub struct XcmBlobHaulerAdapter<XcmBlobHauler>(sp_std::marker::PhantomData<XcmBlobHauler>);
|
pub struct XcmBlobHaulerAdapter<XcmBlobHauler, Lanes>(
|
||||||
|
sp_std::marker::PhantomData<(XcmBlobHauler, Lanes)>,
|
||||||
|
);
|
||||||
|
|
||||||
impl<H: XcmBlobHauler> HaulBlob for XcmBlobHaulerAdapter<H>
|
impl<
|
||||||
where
|
H: XcmBlobHauler,
|
||||||
H::Runtime: MessagesConfig<H::MessagesInstance, OutboundPayload = XcmAsPlainPayload>,
|
Lanes: Get<sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))>>,
|
||||||
|
> OnMessagesDelivered for XcmBlobHaulerAdapter<H, Lanes>
|
||||||
{
|
{
|
||||||
fn haul_blob(blob: sp_std::prelude::Vec<u8>) -> Result<(), HaulBlobError> {
|
|
||||||
let sender_and_lane = H::SenderAndLane::get();
|
|
||||||
MessagesPallet::<H::Runtime, H::MessagesInstance>::send_message(sender_and_lane.lane, blob)
|
|
||||||
.map(|artifacts| {
|
|
||||||
log::info!(
|
|
||||||
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
|
|
||||||
"haul_blob result - ok: {:?} on lane: {:?}. Enqueued messages: {}",
|
|
||||||
artifacts.nonce,
|
|
||||||
sender_and_lane.lane,
|
|
||||||
artifacts.enqueued_messages,
|
|
||||||
);
|
|
||||||
|
|
||||||
// notify XCM queue manager about updated lane state
|
|
||||||
LocalXcmQueueManager::<H>::on_bridge_message_enqueued(
|
|
||||||
&sender_and_lane,
|
|
||||||
artifacts.enqueued_messages,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.map_err(|error| {
|
|
||||||
log::error!(
|
|
||||||
target: crate::LOG_TARGET_BRIDGE_DISPATCH,
|
|
||||||
"haul_blob result - error: {:?} on lane: {:?}",
|
|
||||||
error,
|
|
||||||
sender_and_lane.lane,
|
|
||||||
);
|
|
||||||
HaulBlobError::Transport("MessageSenderError")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H: XcmBlobHauler> OnMessagesDelivered for XcmBlobHaulerAdapter<H> {
|
|
||||||
fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) {
|
fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) {
|
||||||
let sender_and_lane = H::SenderAndLane::get();
|
if let Some(sender_and_lane) =
|
||||||
if sender_and_lane.lane != lane {
|
Lanes::get().iter().find(|link| link.0.lane == lane).map(|link| &link.0)
|
||||||
return
|
{
|
||||||
|
// notify XCM queue manager about updated lane state
|
||||||
|
LocalXcmQueueManager::<H>::on_bridge_messages_delivered(
|
||||||
|
sender_and_lane,
|
||||||
|
enqueued_messages,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify XCM queue manager about updated lane state
|
|
||||||
LocalXcmQueueManager::<H>::on_bridge_messages_delivered(
|
|
||||||
&sender_and_lane,
|
|
||||||
enqueued_messages,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +323,9 @@ mod tests {
|
|||||||
location: MultiLocation::new(1, X1(Parachain(1000))),
|
location: MultiLocation::new(1, X1(Parachain(1000))),
|
||||||
lane: TEST_LANE_ID,
|
lane: TEST_LANE_ID,
|
||||||
};
|
};
|
||||||
|
pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![
|
||||||
|
(TestSenderAndLane::get(), (NetworkId::ByGenesis([0; 32]), InteriorMultiLocation::Here))
|
||||||
|
];
|
||||||
pub DummyXcmMessage: Xcm<()> = Xcm::new();
|
pub DummyXcmMessage: Xcm<()> = Xcm::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,37 +359,44 @@ mod tests {
|
|||||||
impl XcmBlobHauler for TestBlobHauler {
|
impl XcmBlobHauler for TestBlobHauler {
|
||||||
type Runtime = TestRuntime;
|
type Runtime = TestRuntime;
|
||||||
type MessagesInstance = ();
|
type MessagesInstance = ();
|
||||||
type SenderAndLane = TestSenderAndLane;
|
|
||||||
|
|
||||||
type ToSourceChainSender = DummySendXcm;
|
type ToSourceChainSender = DummySendXcm;
|
||||||
type CongestedMessage = DummyXcmMessage;
|
type CongestedMessage = DummyXcmMessage;
|
||||||
type UncongestedMessage = DummyXcmMessage;
|
type UncongestedMessage = DummyXcmMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestBlobHaulerAdapter = XcmBlobHaulerAdapter<TestBlobHauler>;
|
type TestBlobHaulerAdapter = XcmBlobHaulerAdapter<TestBlobHauler, TestLanes>;
|
||||||
|
|
||||||
fn fill_up_lane_to_congestion() {
|
fn fill_up_lane_to_congestion() -> MessageNonce {
|
||||||
|
let latest_generated_nonce = OUTBOUND_LANE_CONGESTED_THRESHOLD;
|
||||||
OutboundLanes::<TestRuntime, ()>::insert(
|
OutboundLanes::<TestRuntime, ()>::insert(
|
||||||
TEST_LANE_ID,
|
TEST_LANE_ID,
|
||||||
OutboundLaneData {
|
OutboundLaneData {
|
||||||
oldest_unpruned_nonce: 0,
|
oldest_unpruned_nonce: 0,
|
||||||
latest_received_nonce: 0,
|
latest_received_nonce: 0,
|
||||||
latest_generated_nonce: OUTBOUND_LANE_CONGESTED_THRESHOLD,
|
latest_generated_nonce,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
latest_generated_nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn congested_signal_is_not_sent_twice() {
|
fn congested_signal_is_not_sent_twice() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
fill_up_lane_to_congestion();
|
let enqueued = fill_up_lane_to_congestion();
|
||||||
|
|
||||||
// next sent message leads to congested signal
|
// next sent message leads to congested signal
|
||||||
TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap();
|
LocalXcmQueueManager::<TestBlobHauler>::on_bridge_message_enqueued(
|
||||||
|
&TestSenderAndLane::get(),
|
||||||
|
enqueued + 1,
|
||||||
|
);
|
||||||
assert_eq!(DummySendXcm::messages_sent(), 1);
|
assert_eq!(DummySendXcm::messages_sent(), 1);
|
||||||
|
|
||||||
// next sent message => we don't sent another congested signal
|
// next sent message => we don't sent another congested signal
|
||||||
TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap();
|
LocalXcmQueueManager::<TestBlobHauler>::on_bridge_message_enqueued(
|
||||||
|
&TestSenderAndLane::get(),
|
||||||
|
enqueued,
|
||||||
|
);
|
||||||
assert_eq!(DummySendXcm::messages_sent(), 1);
|
assert_eq!(DummySendXcm::messages_sent(), 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -427,7 +404,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn congested_signal_is_not_sent_when_outbound_lane_is_not_congested() {
|
fn congested_signal_is_not_sent_when_outbound_lane_is_not_congested() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap();
|
LocalXcmQueueManager::<TestBlobHauler>::on_bridge_message_enqueued(
|
||||||
|
&TestSenderAndLane::get(),
|
||||||
|
1,
|
||||||
|
);
|
||||||
assert_eq!(DummySendXcm::messages_sent(), 0);
|
assert_eq!(DummySendXcm::messages_sent(), 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -435,10 +415,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn congested_signal_is_sent_when_outbound_lane_is_congested() {
|
fn congested_signal_is_sent_when_outbound_lane_is_congested() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
fill_up_lane_to_congestion();
|
let enqueued = fill_up_lane_to_congestion();
|
||||||
|
|
||||||
// next sent message leads to congested signal
|
// next sent message leads to congested signal
|
||||||
TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap();
|
LocalXcmQueueManager::<TestBlobHauler>::on_bridge_message_enqueued(
|
||||||
|
&TestSenderAndLane::get(),
|
||||||
|
enqueued + 1,
|
||||||
|
);
|
||||||
assert_eq!(DummySendXcm::messages_sent(), 1);
|
assert_eq!(DummySendXcm::messages_sent(), 1);
|
||||||
assert!(LocalXcmQueueManager::<TestBlobHauler>::is_congested_signal_sent(TEST_LANE_ID));
|
assert!(LocalXcmQueueManager::<TestBlobHauler>::is_congested_signal_sent(TEST_LANE_ID));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -376,8 +376,8 @@ impl ChainWithGrandpa for BridgedUnderlyingChain {
|
|||||||
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
||||||
const MAX_AUTHORITIES_COUNT: u32 = 16;
|
const MAX_AUTHORITIES_COUNT: u32 = 16;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
||||||
const MAX_HEADER_SIZE: u32 = 256;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
|
const AVERAGE_HEADER_SIZE: u32 = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chain for BridgedUnderlyingParachain {
|
impl Chain for BridgedUnderlyingParachain {
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet};
|
use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet};
|
||||||
use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa};
|
use bp_header_chain::{
|
||||||
|
justification::GrandpaJustification, max_expected_submit_finality_proof_arguments_size,
|
||||||
|
ChainWithGrandpa, GrandpaConsensusLogReader,
|
||||||
|
};
|
||||||
use bp_runtime::{BlockNumberOf, OwnedBridgeModule};
|
use bp_runtime::{BlockNumberOf, OwnedBridgeModule};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight};
|
use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight};
|
||||||
@@ -169,28 +172,28 @@ pub(crate) fn submit_finality_proof_info_from_args<T: Config<I>, I: 'static>(
|
|||||||
Weight::zero()
|
Weight::zero()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// check if the `finality_target` is a mandatory header. If so, we are ready to refund larger
|
||||||
|
// size
|
||||||
|
let is_mandatory_finality_target =
|
||||||
|
GrandpaConsensusLogReader::<BridgedBlockNumber<T, I>>::find_scheduled_change(
|
||||||
|
finality_target.digest(),
|
||||||
|
)
|
||||||
|
.is_some();
|
||||||
|
|
||||||
// we can estimate extra call size easily, without any additional significant overhead
|
// we can estimate extra call size easily, without any additional significant overhead
|
||||||
let actual_call_size: u32 = finality_target
|
let actual_call_size: u32 = finality_target
|
||||||
.encoded_size()
|
.encoded_size()
|
||||||
.saturating_add(justification.encoded_size())
|
.saturating_add(justification.encoded_size())
|
||||||
.saturated_into();
|
.saturated_into();
|
||||||
let max_expected_call_size = max_expected_call_size::<T, I>(required_precommits);
|
let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::<T::BridgedChain>(
|
||||||
|
is_mandatory_finality_target,
|
||||||
|
required_precommits,
|
||||||
|
);
|
||||||
let extra_size = actual_call_size.saturating_sub(max_expected_call_size);
|
let extra_size = actual_call_size.saturating_sub(max_expected_call_size);
|
||||||
|
|
||||||
SubmitFinalityProofInfo { block_number, extra_weight, extra_size }
|
SubmitFinalityProofInfo { block_number, extra_weight, extra_size }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns maximal expected size of `submit_finality_proof` call arguments.
|
|
||||||
fn max_expected_call_size<T: Config<I>, I: 'static>(required_precommits: u32) -> u32 {
|
|
||||||
let max_expected_justification_size =
|
|
||||||
GrandpaJustification::<BridgedHeader<T, I>>::max_reasonable_size::<T::BridgedChain>(
|
|
||||||
required_precommits,
|
|
||||||
);
|
|
||||||
|
|
||||||
// call arguments are header and justification
|
|
||||||
T::BridgedChain::MAX_HEADER_SIZE.saturating_add(max_expected_justification_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ impl ChainWithGrandpa for TestBridgedChain {
|
|||||||
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
||||||
const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES;
|
const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
||||||
const MAX_HEADER_SIZE: u32 = 256;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
|
const AVERAGE_HEADER_SIZE: u32 = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return test externalities to use in tests.
|
/// Return test externalities to use in tests.
|
||||||
|
|||||||
@@ -252,8 +252,8 @@ impl ChainWithGrandpa for TestBridgedChain {
|
|||||||
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
||||||
const MAX_AUTHORITIES_COUNT: u32 = 16;
|
const MAX_AUTHORITIES_COUNT: u32 = 16;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
||||||
const MAX_HEADER_SIZE: u32 = 256;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
|
const AVERAGE_HEADER_SIZE: u32 = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -283,8 +283,8 @@ impl ChainWithGrandpa for OtherBridgedChain {
|
|||||||
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
|
||||||
const MAX_AUTHORITIES_COUNT: u32 = 16;
|
const MAX_AUTHORITIES_COUNT: u32 = 16;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
|
||||||
const MAX_HEADER_SIZE: u32 = 256;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
|
const AVERAGE_HEADER_SIZE: u32 = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return test externalities to use in tests.
|
/// Return test externalities to use in tests.
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
[package]
|
||||||
|
name = "pallet-xcm-bridge-hub"
|
||||||
|
description = "Module that adds dynamic bridges/lanes support to XCM infrastucture at the bridge hub."
|
||||||
|
version = "0.1.0"
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false }
|
||||||
|
log = { version = "0.4.20", default-features = false }
|
||||||
|
scale-info = { version = "2.10.0", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
|
# Bridge Dependencies
|
||||||
|
bp-messages = { path = "../../primitives/messages", default-features = false }
|
||||||
|
bp-runtime = { path = "../../primitives/runtime", default-features = false }
|
||||||
|
bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false }
|
||||||
|
pallet-bridge-messages = { path = "../messages", default-features = false }
|
||||||
|
bridge-runtime-common = { path = "../../bin/runtime-common", default-features = false }
|
||||||
|
|
||||||
|
# Substrate Dependencies
|
||||||
|
frame-support = { path = "../../../substrate/frame/support", default-features = false }
|
||||||
|
frame-system = { path = "../../../substrate/frame/system", default-features = false }
|
||||||
|
sp-core = { path = "../../../substrate/primitives/core", default-features = false }
|
||||||
|
sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false }
|
||||||
|
sp-std = { path = "../../../substrate/primitives/std", default-features = false }
|
||||||
|
|
||||||
|
# Polkadot Dependencies
|
||||||
|
xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false }
|
||||||
|
xcm-builder = { package = "staging-xcm-builder", path = "../../../polkadot/xcm/xcm-builder", default-features = false }
|
||||||
|
xcm-executor = { package = "staging-xcm-executor", path = "../../../polkadot/xcm/xcm-executor", default-features = false }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
bp-header-chain = { path = "../../primitives/header-chain" }
|
||||||
|
pallet-balances = { path = "../../../substrate/frame/balances" }
|
||||||
|
sp-io = { path = "../../../substrate/primitives/io" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = [
|
||||||
|
"bp-messages/std",
|
||||||
|
"bp-runtime/std",
|
||||||
|
"bp-xcm-bridge-hub/std",
|
||||||
|
"bridge-runtime-common/std",
|
||||||
|
"codec/std",
|
||||||
|
"frame-support/std",
|
||||||
|
"frame-system/std",
|
||||||
|
"log/std",
|
||||||
|
"pallet-bridge-messages/std",
|
||||||
|
"scale-info/std",
|
||||||
|
"sp-core/std",
|
||||||
|
"sp-runtime/std",
|
||||||
|
"sp-std/std",
|
||||||
|
"xcm-builder/std",
|
||||||
|
"xcm-executor/std",
|
||||||
|
"xcm/std",
|
||||||
|
]
|
||||||
|
runtime-benchmarks = [
|
||||||
|
"bridge-runtime-common/runtime-benchmarks",
|
||||||
|
"frame-support/runtime-benchmarks",
|
||||||
|
"frame-system/runtime-benchmarks",
|
||||||
|
"pallet-balances/runtime-benchmarks",
|
||||||
|
"pallet-bridge-messages/runtime-benchmarks",
|
||||||
|
"sp-runtime/runtime-benchmarks",
|
||||||
|
"xcm-builder/runtime-benchmarks",
|
||||||
|
"xcm-executor/runtime-benchmarks",
|
||||||
|
]
|
||||||
|
try-runtime = [
|
||||||
|
"frame-support/try-runtime",
|
||||||
|
"frame-system/try-runtime",
|
||||||
|
"pallet-balances/try-runtime",
|
||||||
|
"pallet-bridge-messages/try-runtime",
|
||||||
|
"sp-runtime/try-runtime",
|
||||||
|
]
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! The code that allows to use the pallet (`pallet-xcm-bridge-hub`) as XCM message
|
||||||
|
//! exporter at the sending bridge hub. Internally, it just enqueues outbound blob
|
||||||
|
//! in the messages pallet queue.
|
||||||
|
//!
|
||||||
|
//! This code is executed at the source bridge hub.
|
||||||
|
|
||||||
|
use crate::{Config, Pallet, LOG_TARGET};
|
||||||
|
|
||||||
|
use bp_messages::source_chain::MessagesBridge;
|
||||||
|
use bp_xcm_bridge_hub::XcmAsPlainPayload;
|
||||||
|
use bridge_runtime_common::messages_xcm_extension::{LocalXcmQueueManager, SenderAndLane};
|
||||||
|
use pallet_bridge_messages::{Config as BridgeMessagesConfig, Pallet as BridgeMessagesPallet};
|
||||||
|
use xcm::prelude::*;
|
||||||
|
use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter};
|
||||||
|
use xcm_executor::traits::ExportXcm;
|
||||||
|
|
||||||
|
/// An easy way to access `HaulBlobExporter`.
|
||||||
|
pub type PalletAsHaulBlobExporter<T, I> = HaulBlobExporter<
|
||||||
|
DummyHaulBlob,
|
||||||
|
<T as Config<I>>::BridgedNetworkId,
|
||||||
|
<T as Config<I>>::MessageExportPrice,
|
||||||
|
>;
|
||||||
|
/// An easy way to access associated messages pallet.
|
||||||
|
type MessagesPallet<T, I> = BridgeMessagesPallet<T, <T as Config<I>>::BridgeMessagesPalletInstance>;
|
||||||
|
|
||||||
|
impl<T: Config<I>, I: 'static> ExportXcm for Pallet<T, I>
|
||||||
|
where
|
||||||
|
T: BridgeMessagesConfig<
|
||||||
|
<T as Config<I>>::BridgeMessagesPalletInstance,
|
||||||
|
OutboundPayload = XcmAsPlainPayload,
|
||||||
|
>,
|
||||||
|
{
|
||||||
|
type Ticket = (SenderAndLane, XcmAsPlainPayload, XcmHash);
|
||||||
|
|
||||||
|
fn validate(
|
||||||
|
network: NetworkId,
|
||||||
|
channel: u32,
|
||||||
|
universal_source: &mut Option<InteriorMultiLocation>,
|
||||||
|
destination: &mut Option<InteriorMultiLocation>,
|
||||||
|
message: &mut Option<Xcm<()>>,
|
||||||
|
) -> Result<(Self::Ticket, MultiAssets), SendError> {
|
||||||
|
// Find supported lane_id.
|
||||||
|
let sender_and_lane = Self::lane_for(
|
||||||
|
universal_source.as_ref().ok_or(SendError::MissingArgument)?,
|
||||||
|
(&network, destination.as_ref().ok_or(SendError::MissingArgument)?),
|
||||||
|
)
|
||||||
|
.ok_or(SendError::NotApplicable)?;
|
||||||
|
|
||||||
|
// check if we are able to route the message. We use existing `HaulBlobExporter` for that.
|
||||||
|
// It will make all required changes and will encode message properly, so that the
|
||||||
|
// `DispatchBlob` at the bridged bridge hub will be able to decode it
|
||||||
|
let ((blob, id), price) = PalletAsHaulBlobExporter::<T, I>::validate(
|
||||||
|
network,
|
||||||
|
channel,
|
||||||
|
universal_source,
|
||||||
|
destination,
|
||||||
|
message,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(((sender_and_lane, blob, id), price))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deliver(
|
||||||
|
(sender_and_lane, blob, id): (SenderAndLane, XcmAsPlainPayload, XcmHash),
|
||||||
|
) -> Result<XcmHash, SendError> {
|
||||||
|
let lane_id = sender_and_lane.lane;
|
||||||
|
let send_result = MessagesPallet::<T, I>::send_message(lane_id, blob);
|
||||||
|
|
||||||
|
match send_result {
|
||||||
|
Ok(artifacts) => {
|
||||||
|
log::info!(
|
||||||
|
target: LOG_TARGET,
|
||||||
|
"XCM message {:?} has been enqueued at bridge {:?} with nonce {}",
|
||||||
|
id,
|
||||||
|
lane_id,
|
||||||
|
artifacts.nonce,
|
||||||
|
);
|
||||||
|
|
||||||
|
// notify XCM queue manager about updated lane state
|
||||||
|
LocalXcmQueueManager::<T::LanesSupport>::on_bridge_message_enqueued(
|
||||||
|
&sender_and_lane,
|
||||||
|
artifacts.enqueued_messages,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Err(error) => {
|
||||||
|
log::debug!(
|
||||||
|
target: LOG_TARGET,
|
||||||
|
"XCM message {:?} has been dropped because of bridge error {:?} on bridge {:?}",
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
lane_id,
|
||||||
|
);
|
||||||
|
return Err(SendError::Transport("BridgeSendError"))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dummy implementation of the `HaulBlob` trait that is never called.
|
||||||
|
///
|
||||||
|
/// We are using `HaulBlobExporter`, which requires `HaulBlob` implementation. It assumes that
|
||||||
|
/// there's a single channel between two bridge hubs - `HaulBlob` only accepts the blob and nothing
|
||||||
|
/// else. But bridge messages pallet may have a dedicated channel (lane) for every pair of bridged
|
||||||
|
/// chains. So we are using our own `ExportXcm` implementation, but to utilize `HaulBlobExporter` we
|
||||||
|
/// still need this `DummyHaulBlob`.
|
||||||
|
pub struct DummyHaulBlob;
|
||||||
|
|
||||||
|
impl HaulBlob for DummyHaulBlob {
|
||||||
|
fn haul_blob(_blob: XcmAsPlainPayload) -> Result<(), HaulBlobError> {
|
||||||
|
Err(HaulBlobError::Transport("DummyHaulBlob"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::mock::*;
|
||||||
|
use frame_support::assert_ok;
|
||||||
|
use xcm_executor::traits::export_xcm;
|
||||||
|
|
||||||
|
fn universal_source() -> InteriorMultiLocation {
|
||||||
|
X2(GlobalConsensus(RelayNetwork::get()), Parachain(SIBLING_ASSET_HUB_ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn universal_destination() -> InteriorMultiLocation {
|
||||||
|
BridgedDestination::get()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn export_works() {
|
||||||
|
run_test(|| {
|
||||||
|
assert_ok!(export_xcm::<XcmOverBridge>(
|
||||||
|
BridgedRelayNetwork::get(),
|
||||||
|
0,
|
||||||
|
universal_source(),
|
||||||
|
universal_destination(),
|
||||||
|
vec![Instruction::ClearOrigin].into(),
|
||||||
|
));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn export_fails_if_argument_is_missing() {
|
||||||
|
run_test(|| {
|
||||||
|
assert_eq!(
|
||||||
|
XcmOverBridge::validate(
|
||||||
|
BridgedRelayNetwork::get(),
|
||||||
|
0,
|
||||||
|
&mut None,
|
||||||
|
&mut Some(universal_destination()),
|
||||||
|
&mut Some(Vec::new().into()),
|
||||||
|
),
|
||||||
|
Err(SendError::MissingArgument),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
XcmOverBridge::validate(
|
||||||
|
BridgedRelayNetwork::get(),
|
||||||
|
0,
|
||||||
|
&mut Some(universal_source()),
|
||||||
|
&mut None,
|
||||||
|
&mut Some(Vec::new().into()),
|
||||||
|
),
|
||||||
|
Err(SendError::MissingArgument),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exporter_computes_correct_lane_id() {
|
||||||
|
run_test(|| {
|
||||||
|
let expected_lane_id = TEST_LANE_ID;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
XcmOverBridge::validate(
|
||||||
|
BridgedRelayNetwork::get(),
|
||||||
|
0,
|
||||||
|
&mut Some(universal_source()),
|
||||||
|
&mut Some(universal_destination()),
|
||||||
|
&mut Some(Vec::new().into()),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.0
|
||||||
|
.lane,
|
||||||
|
expected_lane_id,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Module that adds XCM support to bridge pallets.
|
||||||
|
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
use bridge_runtime_common::messages_xcm_extension::XcmBlobHauler;
|
||||||
|
use pallet_bridge_messages::Config as BridgeMessagesConfig;
|
||||||
|
use xcm::prelude::*;
|
||||||
|
|
||||||
|
pub use exporter::PalletAsHaulBlobExporter;
|
||||||
|
pub use pallet::*;
|
||||||
|
|
||||||
|
mod exporter;
|
||||||
|
mod mock;
|
||||||
|
|
||||||
|
/// The target that will be used when publishing logs related to this pallet.
|
||||||
|
pub const LOG_TARGET: &str = "runtime::bridge-xcm";
|
||||||
|
|
||||||
|
#[frame_support::pallet]
|
||||||
|
pub mod pallet {
|
||||||
|
use super::*;
|
||||||
|
use bridge_runtime_common::messages_xcm_extension::SenderAndLane;
|
||||||
|
use frame_support::pallet_prelude::*;
|
||||||
|
|
||||||
|
#[pallet::config]
|
||||||
|
#[pallet::disable_frame_system_supertrait_check]
|
||||||
|
pub trait Config<I: 'static = ()>:
|
||||||
|
BridgeMessagesConfig<Self::BridgeMessagesPalletInstance>
|
||||||
|
{
|
||||||
|
/// Runtime's universal location.
|
||||||
|
type UniversalLocation: Get<InteriorMultiLocation>;
|
||||||
|
// TODO: https://github.com/paritytech/parity-bridges-common/issues/1666 remove `ChainId` and
|
||||||
|
// replace it with the `NetworkId` - then we'll be able to use
|
||||||
|
// `T as pallet_bridge_messages::Config<T::BridgeMessagesPalletInstance>::BridgedChain::NetworkId`
|
||||||
|
/// Bridged network id.
|
||||||
|
#[pallet::constant]
|
||||||
|
type BridgedNetworkId: Get<NetworkId>;
|
||||||
|
/// Associated messages pallet instance that bridges us with the
|
||||||
|
/// `BridgedNetworkId` consensus.
|
||||||
|
type BridgeMessagesPalletInstance: 'static;
|
||||||
|
|
||||||
|
/// Price of single message export to the bridged consensus (`Self::BridgedNetworkId`).
|
||||||
|
type MessageExportPrice: Get<MultiAssets>;
|
||||||
|
|
||||||
|
/// Get point-to-point links with bridged consensus (`Self::BridgedNetworkId`).
|
||||||
|
/// (this will be replaced with dynamic on-chain bridges - `Bridges V2`)
|
||||||
|
type Lanes: Get<sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))>>;
|
||||||
|
/// Support for point-to-point links
|
||||||
|
/// (this will be replaced with dynamic on-chain bridges - `Bridges V2`)
|
||||||
|
type LanesSupport: XcmBlobHauler;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pallet::pallet]
|
||||||
|
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||||
|
|
||||||
|
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||||
|
/// Returns dedicated/configured lane identifier.
|
||||||
|
pub(crate) fn lane_for(
|
||||||
|
source: &InteriorMultiLocation,
|
||||||
|
dest: (&NetworkId, &InteriorMultiLocation),
|
||||||
|
) -> Option<SenderAndLane> {
|
||||||
|
let source = source.relative_to(&T::UniversalLocation::get());
|
||||||
|
|
||||||
|
// Check that we have configured a point-to-point lane for 'source' and `dest`.
|
||||||
|
T::Lanes::get()
|
||||||
|
.into_iter()
|
||||||
|
.find_map(|(lane_source, (lane_dest_network, lane_dest))| {
|
||||||
|
if lane_source.location == source &&
|
||||||
|
&lane_dest_network == dest.0 &&
|
||||||
|
&T::BridgedNetworkId::get() == dest.0 &&
|
||||||
|
&lane_dest == dest.1
|
||||||
|
{
|
||||||
|
Some(lane_source)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,328 @@
|
|||||||
|
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
use crate as pallet_xcm_bridge_hub;
|
||||||
|
|
||||||
|
use bp_messages::{
|
||||||
|
source_chain::LaneMessageVerifier,
|
||||||
|
target_chain::{DispatchMessage, MessageDispatch},
|
||||||
|
LaneId, OutboundLaneData, VerificationError,
|
||||||
|
};
|
||||||
|
use bp_runtime::{messages::MessageDispatchResult, Chain, UnderlyingChainProvider};
|
||||||
|
use bridge_runtime_common::{
|
||||||
|
messages::{
|
||||||
|
source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter,
|
||||||
|
BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages,
|
||||||
|
},
|
||||||
|
messages_xcm_extension::{SenderAndLane, XcmBlobHauler},
|
||||||
|
};
|
||||||
|
use codec::Encode;
|
||||||
|
use frame_support::{derive_impl, parameter_types, traits::ConstU32, weights::RuntimeDbWeight};
|
||||||
|
use sp_core::H256;
|
||||||
|
use sp_runtime::{
|
||||||
|
testing::Header as SubstrateHeader,
|
||||||
|
traits::{BlakeTwo256, IdentityLookup},
|
||||||
|
AccountId32, BuildStorage,
|
||||||
|
};
|
||||||
|
use xcm::prelude::*;
|
||||||
|
|
||||||
|
pub type AccountId = AccountId32;
|
||||||
|
pub type Balance = u64;
|
||||||
|
|
||||||
|
type Block = frame_system::mocking::MockBlock<TestRuntime>;
|
||||||
|
|
||||||
|
pub const SIBLING_ASSET_HUB_ID: u32 = 2001;
|
||||||
|
pub const THIS_BRIDGE_HUB_ID: u32 = 2002;
|
||||||
|
pub const BRIDGED_ASSET_HUB_ID: u32 = 1001;
|
||||||
|
pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 1]);
|
||||||
|
|
||||||
|
frame_support::construct_runtime! {
|
||||||
|
pub enum TestRuntime {
|
||||||
|
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||||
|
Balances: pallet_balances::{Pallet, Event<T>},
|
||||||
|
Messages: pallet_bridge_messages::{Pallet, Call, Event<T>},
|
||||||
|
XcmOverBridge: pallet_xcm_bridge_hub::{Pallet},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 };
|
||||||
|
pub const ExistentialDeposit: Balance = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
||||||
|
impl frame_system::Config for TestRuntime {
|
||||||
|
type AccountId = AccountId;
|
||||||
|
type AccountData = pallet_balances::AccountData<Balance>;
|
||||||
|
type Block = Block;
|
||||||
|
type Lookup = IdentityLookup<Self::AccountId>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
|
||||||
|
impl pallet_balances::Config for TestRuntime {
|
||||||
|
type AccountStore = System;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lane message verifier that is used in tests.
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct TestLaneMessageVerifier;
|
||||||
|
|
||||||
|
impl LaneMessageVerifier<Vec<u8>> for TestLaneMessageVerifier {
|
||||||
|
fn verify_message(
|
||||||
|
_lane: &LaneId,
|
||||||
|
_lane_outbound_data: &OutboundLaneData,
|
||||||
|
_payload: &Vec<u8>,
|
||||||
|
) -> Result<(), VerificationError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl pallet_bridge_messages::Config for TestRuntime {
|
||||||
|
type RuntimeEvent = RuntimeEvent;
|
||||||
|
type WeightInfo = TestMessagesWeights;
|
||||||
|
|
||||||
|
type BridgedChainId = ();
|
||||||
|
type ActiveOutboundLanes = ActiveOutboundLanes;
|
||||||
|
type MaxUnrewardedRelayerEntriesAtInboundLane = ();
|
||||||
|
type MaxUnconfirmedMessagesAtInboundLane = ();
|
||||||
|
type MaximalOutboundPayloadSize = ConstU32<2048>;
|
||||||
|
type OutboundPayload = Vec<u8>;
|
||||||
|
type InboundPayload = Vec<u8>;
|
||||||
|
type InboundRelayer = ();
|
||||||
|
type DeliveryPayments = ();
|
||||||
|
type TargetHeaderChain = TargetHeaderChainAdapter<OnThisChainBridge>;
|
||||||
|
type LaneMessageVerifier = TestLaneMessageVerifier;
|
||||||
|
type DeliveryConfirmationPayments = ();
|
||||||
|
type OnMessagesDelivered = ();
|
||||||
|
type SourceHeaderChain = SourceHeaderChainAdapter<OnThisChainBridge>;
|
||||||
|
type MessageDispatch = TestMessageDispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TestMessagesWeights;
|
||||||
|
|
||||||
|
impl pallet_bridge_messages::WeightInfo for TestMessagesWeights {
|
||||||
|
fn receive_single_message_proof() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
fn receive_delivery_proof_for_single_message() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_two_messages_proof() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_single_message_proof_1_kb() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_single_message_proof_16_kb() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_single_message_proof_with_dispatch(_: u32) -> Weight {
|
||||||
|
Weight::from_parts(1, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl pallet_bridge_messages::WeightInfoExt for TestMessagesWeights {
|
||||||
|
fn expected_extra_storage_proof_size() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_messages_proof_overhead_from_runtime() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const RelayNetwork: NetworkId = NetworkId::Kusama;
|
||||||
|
pub const BridgedRelayNetwork: NetworkId = NetworkId::Polkadot;
|
||||||
|
pub const NonBridgedRelayNetwork: NetworkId = NetworkId::Rococo;
|
||||||
|
pub const BridgeReserve: Balance = 100_000;
|
||||||
|
pub UniversalLocation: InteriorMultiLocation = X2(
|
||||||
|
GlobalConsensus(RelayNetwork::get()),
|
||||||
|
Parachain(THIS_BRIDGE_HUB_ID),
|
||||||
|
);
|
||||||
|
pub const Penalty: Balance = 1_000;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl pallet_xcm_bridge_hub::Config for TestRuntime {
|
||||||
|
type UniversalLocation = UniversalLocation;
|
||||||
|
type BridgedNetworkId = BridgedRelayNetwork;
|
||||||
|
type BridgeMessagesPalletInstance = ();
|
||||||
|
|
||||||
|
type MessageExportPrice = ();
|
||||||
|
type Lanes = TestLanes;
|
||||||
|
type LanesSupport = TestXcmBlobHauler;
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub TestSenderAndLane: SenderAndLane = SenderAndLane {
|
||||||
|
location: MultiLocation::new(1, X1(Parachain(SIBLING_ASSET_HUB_ID))),
|
||||||
|
lane: TEST_LANE_ID,
|
||||||
|
};
|
||||||
|
pub const BridgedDestination: InteriorMultiLocation = X1(
|
||||||
|
Parachain(BRIDGED_ASSET_HUB_ID)
|
||||||
|
);
|
||||||
|
pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![
|
||||||
|
(TestSenderAndLane::get(), (BridgedRelayNetwork::get(), BridgedDestination::get()))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TestXcmBlobHauler;
|
||||||
|
impl XcmBlobHauler for TestXcmBlobHauler {
|
||||||
|
type Runtime = TestRuntime;
|
||||||
|
type MessagesInstance = ();
|
||||||
|
type ToSourceChainSender = ();
|
||||||
|
type CongestedMessage = ();
|
||||||
|
type UncongestedMessage = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ThisChain;
|
||||||
|
|
||||||
|
impl Chain for ThisChain {
|
||||||
|
type BlockNumber = u64;
|
||||||
|
type Hash = H256;
|
||||||
|
type Hasher = BlakeTwo256;
|
||||||
|
type Header = SubstrateHeader;
|
||||||
|
type AccountId = AccountId;
|
||||||
|
type Balance = Balance;
|
||||||
|
type Nonce = u64;
|
||||||
|
type Signature = sp_runtime::MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
u32::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BridgedChain;
|
||||||
|
pub type BridgedHeaderHash = H256;
|
||||||
|
pub type BridgedChainHeader = SubstrateHeader;
|
||||||
|
|
||||||
|
impl Chain for BridgedChain {
|
||||||
|
type BlockNumber = u64;
|
||||||
|
type Hash = BridgedHeaderHash;
|
||||||
|
type Hasher = BlakeTwo256;
|
||||||
|
type Header = BridgedChainHeader;
|
||||||
|
type AccountId = AccountId;
|
||||||
|
type Balance = Balance;
|
||||||
|
type Nonce = u64;
|
||||||
|
type Signature = sp_runtime::MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
4096
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test message dispatcher.
|
||||||
|
pub struct TestMessageDispatch;
|
||||||
|
|
||||||
|
impl TestMessageDispatch {
|
||||||
|
pub fn deactivate(lane: LaneId) {
|
||||||
|
frame_support::storage::unhashed::put(&(b"inactive", lane).encode()[..], &false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageDispatch for TestMessageDispatch {
|
||||||
|
type DispatchPayload = Vec<u8>;
|
||||||
|
type DispatchLevelResult = ();
|
||||||
|
|
||||||
|
fn is_active() -> bool {
|
||||||
|
frame_support::storage::unhashed::take::<bool>(&(b"inactive").encode()[..]) != Some(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_weight(_message: &mut DispatchMessage<Self::DispatchPayload>) -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch(
|
||||||
|
_: DispatchMessage<Self::DispatchPayload>,
|
||||||
|
) -> MessageDispatchResult<Self::DispatchLevelResult> {
|
||||||
|
MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WrappedThisChain;
|
||||||
|
impl UnderlyingChainProvider for WrappedThisChain {
|
||||||
|
type Chain = ThisChain;
|
||||||
|
}
|
||||||
|
impl ThisChainWithMessages for WrappedThisChain {
|
||||||
|
type RuntimeOrigin = RuntimeOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WrappedBridgedChain;
|
||||||
|
impl UnderlyingChainProvider for WrappedBridgedChain {
|
||||||
|
type Chain = BridgedChain;
|
||||||
|
}
|
||||||
|
impl BridgedChainWithMessages for WrappedBridgedChain {}
|
||||||
|
|
||||||
|
pub struct BridgedHeaderChain;
|
||||||
|
impl bp_header_chain::HeaderChain<BridgedChain> for BridgedHeaderChain {
|
||||||
|
fn finalized_header_state_root(
|
||||||
|
_hash: HashOf<WrappedBridgedChain>,
|
||||||
|
) -> Option<HashOf<WrappedBridgedChain>> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bridge that is deployed on `ThisChain` and allows sending/receiving messages to/from
|
||||||
|
/// `BridgedChain`.
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct OnThisChainBridge;
|
||||||
|
|
||||||
|
impl MessageBridge for OnThisChainBridge {
|
||||||
|
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = "";
|
||||||
|
|
||||||
|
type ThisChain = WrappedThisChain;
|
||||||
|
type BridgedChain = WrappedBridgedChain;
|
||||||
|
type BridgedHeaderChain = BridgedHeaderChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run pallet test.
|
||||||
|
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
|
||||||
|
sp_io::TestExternalities::new(
|
||||||
|
frame_system::GenesisConfig::<TestRuntime>::default().build_storage().unwrap(),
|
||||||
|
)
|
||||||
|
.execute_with(test)
|
||||||
|
}
|
||||||
@@ -52,8 +52,8 @@ impl ChainWithGrandpa for Kusama {
|
|||||||
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||||
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||||
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The SignedExtension used by Kusama.
|
// The SignedExtension used by Kusama.
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidi
|
|||||||
// This chain reuses most of Polkadot primitives.
|
// This chain reuses most of Polkadot primitives.
|
||||||
pub use bp_polkadot_core::{
|
pub use bp_polkadot_core::{
|
||||||
AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature,
|
AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature,
|
||||||
SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE_IN_JUSTIFICATION,
|
SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE, EXTRA_STORAGE_PROOF_SIZE,
|
||||||
EXTRA_STORAGE_PROOF_SIZE, MAX_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY,
|
MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Maximal number of GRANDPA authorities at Polkadot Bulletin chain.
|
/// Maximal number of GRANDPA authorities at Polkadot Bulletin chain.
|
||||||
@@ -207,8 +207,8 @@ impl ChainWithGrandpa for PolkadotBulletin {
|
|||||||
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||||
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||||
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa);
|
decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa);
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ impl ChainWithGrandpa for Polkadot {
|
|||||||
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||||
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||||
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SignedExtension used by Polkadot.
|
/// The SignedExtension used by Polkadot.
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ impl ChainWithGrandpa for Rococo {
|
|||||||
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||||
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||||
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ impl ChainWithGrandpa for Westend {
|
|||||||
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||||
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||||
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
|
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ impl<H: HeaderT> GrandpaJustification<H> {
|
|||||||
.saturating_add(BlockNumberOf::<C>::max_encoded_len().saturated_into())
|
.saturating_add(BlockNumberOf::<C>::max_encoded_len().saturated_into())
|
||||||
.saturating_add(HashOf::<C>::max_encoded_len().saturated_into());
|
.saturating_add(HashOf::<C>::max_encoded_len().saturated_into());
|
||||||
|
|
||||||
let max_expected_votes_ancestries_size = C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY
|
let max_expected_votes_ancestries_size =
|
||||||
.saturating_mul(C::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION);
|
C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE);
|
||||||
|
|
||||||
// justification is round number (u64=8b), a signed GRANDPA commit and the
|
// justification is round number (u64=8b), a signed GRANDPA commit and the
|
||||||
// `votes_ancestries` vector
|
// `votes_ancestries` vector
|
||||||
|
|||||||
@@ -266,23 +266,28 @@ pub trait ChainWithGrandpa: Chain {
|
|||||||
/// to submitter.
|
/// to submitter.
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32;
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32;
|
||||||
|
|
||||||
/// Maximal size of the chain header. The header may be the header that enacts new GRANDPA
|
/// Maximal size of the mandatory chain header. Mandatory header is the header that enacts new
|
||||||
/// authorities set (so it has large digest inside).
|
/// GRANDPA authorities set (so it has large digest inside).
|
||||||
///
|
///
|
||||||
/// This isn't a strict limit. The relay may submit larger headers and the pallet will accept
|
/// This isn't a strict limit. The relay may submit larger headers and the pallet will accept
|
||||||
/// the call. The limit is only used to compute maximal refund amount and doing calls which
|
/// the call. The limit is only used to compute maximal refund amount and doing calls which
|
||||||
/// exceed the limit, may be costly to submitter.
|
/// exceed the limit, may be costly to submitter.
|
||||||
const MAX_HEADER_SIZE: u32;
|
const MAX_MANDATORY_HEADER_SIZE: u32;
|
||||||
|
|
||||||
/// Average size of the chain header from justification ancestry. We don't expect to see there
|
/// Average size of the chain header. We don't expect to see there headers that change GRANDPA
|
||||||
/// headers that change GRANDPA authorities set (GRANDPA will probably be able to finalize at
|
/// authorities set (GRANDPA will probably be able to finalize at least one additional header
|
||||||
/// least one additional header per session on non test chains), so this is average size of
|
/// per session on non test chains), so this is average size of headers that aren't changing the
|
||||||
/// headers that aren't changing the set.
|
/// set.
|
||||||
///
|
///
|
||||||
/// This isn't a strict limit. The relay may submit justifications with larger headers in its
|
/// This isn't a strict limit. The relay may submit justifications with larger headers and the
|
||||||
/// ancestry and the pallet will accept the call. The limit is only used to compute maximal
|
/// pallet will accept the call. However, if the total size of all `submit_finality_proof`
|
||||||
/// refund amount and doing calls which exceed the limit, may be costly to submitter.
|
/// arguments exceeds the maximal size, computed using this average size, relayer will only get
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32;
|
/// partial refund.
|
||||||
|
///
|
||||||
|
/// We expect some headers on production chains that are above this size. But they are rare and
|
||||||
|
/// if rellayer cares about its profitability, we expect it'll select other headers for
|
||||||
|
/// submission.
|
||||||
|
const AVERAGE_HEADER_SIZE: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ChainWithGrandpa for T
|
impl<T> ChainWithGrandpa for T
|
||||||
@@ -295,7 +300,67 @@ where
|
|||||||
const MAX_AUTHORITIES_COUNT: u32 = <T::Chain as ChainWithGrandpa>::MAX_AUTHORITIES_COUNT;
|
const MAX_AUTHORITIES_COUNT: u32 = <T::Chain as ChainWithGrandpa>::MAX_AUTHORITIES_COUNT;
|
||||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||||
<T::Chain as ChainWithGrandpa>::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
<T::Chain as ChainWithGrandpa>::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||||
const MAX_HEADER_SIZE: u32 = <T::Chain as ChainWithGrandpa>::MAX_HEADER_SIZE;
|
const MAX_MANDATORY_HEADER_SIZE: u32 =
|
||||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 =
|
<T::Chain as ChainWithGrandpa>::MAX_MANDATORY_HEADER_SIZE;
|
||||||
<T::Chain as ChainWithGrandpa>::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
const AVERAGE_HEADER_SIZE: u32 = <T::Chain as ChainWithGrandpa>::AVERAGE_HEADER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns maximal expected size of `submit_finality_proof` call arguments.
|
||||||
|
pub fn max_expected_submit_finality_proof_arguments_size<C: ChainWithGrandpa>(
|
||||||
|
is_mandatory_finality_target: bool,
|
||||||
|
precommits: u32,
|
||||||
|
) -> u32 {
|
||||||
|
let max_expected_justification_size =
|
||||||
|
GrandpaJustification::<HeaderOf<C>>::max_reasonable_size::<C>(precommits);
|
||||||
|
|
||||||
|
// call arguments are header and justification
|
||||||
|
let max_expected_finality_target_size = if is_mandatory_finality_target {
|
||||||
|
C::MAX_MANDATORY_HEADER_SIZE
|
||||||
|
} else {
|
||||||
|
C::AVERAGE_HEADER_SIZE
|
||||||
|
};
|
||||||
|
max_expected_finality_target_size.saturating_add(max_expected_justification_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use frame_support::weights::Weight;
|
||||||
|
use sp_runtime::{testing::H256, traits::BlakeTwo256, MultiSignature};
|
||||||
|
|
||||||
|
struct TestChain;
|
||||||
|
|
||||||
|
impl Chain for TestChain {
|
||||||
|
type BlockNumber = u32;
|
||||||
|
type Hash = H256;
|
||||||
|
type Hasher = BlakeTwo256;
|
||||||
|
type Header = sp_runtime::generic::Header<u32, BlakeTwo256>;
|
||||||
|
type AccountId = u64;
|
||||||
|
type Balance = u64;
|
||||||
|
type Nonce = u64;
|
||||||
|
type Signature = MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChainWithGrandpa for TestChain {
|
||||||
|
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "Test";
|
||||||
|
const MAX_AUTHORITIES_COUNT: u32 = 128;
|
||||||
|
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2;
|
||||||
|
const MAX_MANDATORY_HEADER_SIZE: u32 = 100_000;
|
||||||
|
const AVERAGE_HEADER_SIZE: u32 = 1_024;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn max_expected_submit_finality_proof_arguments_size_respects_mandatory_argument() {
|
||||||
|
assert!(
|
||||||
|
max_expected_submit_finality_proof_arguments_size::<TestChain>(true, 100) >
|
||||||
|
max_expected_submit_finality_proof_arguments_size::<TestChain>(false, 100),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,30 +64,28 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256;
|
|||||||
///
|
///
|
||||||
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
|
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
|
||||||
///
|
///
|
||||||
/// This value comes from recent (February, 2023) Kusama and Polkadot headers. There are no
|
/// This value comes from recent (December, 2023) Kusama and Polkadot headers. There are no
|
||||||
/// justifications with any additional headers in votes ancestry, so reasonable headers may
|
/// justifications with any additional headers in votes ancestry, so reasonable headers may
|
||||||
/// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some
|
/// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some
|
||||||
/// reserve here.
|
/// reserve here.
|
||||||
pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2;
|
pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2;
|
||||||
|
|
||||||
/// Approximate average header size in `votes_ancestries` field of justification on Polkadot-like
|
/// Average header size in `votes_ancestries` field of justification on Polkadot-like
|
||||||
/// chains.
|
/// chains.
|
||||||
///
|
///
|
||||||
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
|
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
|
||||||
///
|
///
|
||||||
/// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but some
|
/// This value comes from recent (December, 2023) Kusama headers. Most of headers are `327` bytes
|
||||||
/// non-mandatory headers has size `40kb` (they contain the BABE epoch descriptor with all
|
/// there, but let's have some reserve and make it 1024.
|
||||||
/// authorities - just like our mandatory header). Since we assume `2` headers in justification
|
pub const AVERAGE_HEADER_SIZE: u32 = 1024;
|
||||||
/// votes ancestry, let's set average header to `40kb / 2`.
|
|
||||||
pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024;
|
|
||||||
|
|
||||||
/// Approximate maximal header size on Polkadot-like chains.
|
/// Approximate maximal header size on Polkadot-like chains.
|
||||||
///
|
///
|
||||||
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
|
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
|
||||||
///
|
///
|
||||||
/// This value comes from recent (February, 2023) Kusama headers. Maximal header is a mandatory
|
/// This value comes from recent (December, 2023) Kusama headers. Maximal header is a mandatory
|
||||||
/// header. In its SCALE-encoded form it is `80348` bytes. Let's have some reserve here.
|
/// header. In its SCALE-encoded form it is `113407` bytes. Let's have some reserve here.
|
||||||
pub const MAX_HEADER_SIZE: u32 = 90_000;
|
pub const MAX_MANDATORY_HEADER_SIZE: u32 = 120 * 1024;
|
||||||
|
|
||||||
/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
|
/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
|
||||||
/// Polkadot-like chain. This mostly depends on number of entries in the storage trie.
|
/// Polkadot-like chain. This mostly depends on number of entries in the storage trie.
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "bp-xcm-bridge-hub"
|
||||||
|
description = "Primitives of the xcm-bridge-hub pallet."
|
||||||
|
version = "0.1.0"
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
# Substrate Dependencies
|
||||||
|
sp-std = { path = "../../../substrate/primitives/std", default-features = false }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = ["sp-std/std"]
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Primitives of the xcm-bridge-hub pallet.
|
||||||
|
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
/// Encoded XCM blob. We expect the bridge messages pallet to use this blob type for both inbound
|
||||||
|
/// and outbound payloads.
|
||||||
|
pub type XcmAsPlainPayload = sp_std::vec::Vec<u8>;
|
||||||
+4
-33
@@ -16,7 +16,7 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn send_xcm_from_rococo_relay_to_westend_asset_hub() {
|
fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable() {
|
||||||
// Init tests variables
|
// Init tests variables
|
||||||
// XcmPallet send arguments
|
// XcmPallet send arguments
|
||||||
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
|
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
|
||||||
@@ -53,7 +53,8 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub() {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// Receive XCM message in Bridge Hub source Parachain
|
// Receive XCM message in Bridge Hub source Parachain, it should fail, because we don't have
|
||||||
|
// opened bridge/lane.
|
||||||
BridgeHubRococo::execute_with(|| {
|
BridgeHubRococo::execute_with(|| {
|
||||||
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
|
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
|
||||||
|
|
||||||
@@ -61,37 +62,7 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub() {
|
|||||||
BridgeHubRococo,
|
BridgeHubRococo,
|
||||||
vec![
|
vec![
|
||||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed {
|
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed {
|
||||||
success: true,
|
success: false,
|
||||||
..
|
|
||||||
}) => {},
|
|
||||||
RuntimeEvent::BridgeWestendMessages(pallet_bridge_messages::Event::MessageAccepted {
|
|
||||||
lane_id: LaneId([0, 0, 0, 2]),
|
|
||||||
nonce: 1,
|
|
||||||
}) => {},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Westend Global Consensus
|
|
||||||
// Receive XCM message in Bridge Hub target Parachain
|
|
||||||
BridgeHubWestend::execute_with(|| {
|
|
||||||
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
|
|
||||||
|
|
||||||
assert_expected_events!(
|
|
||||||
BridgeHubWestend,
|
|
||||||
vec![
|
|
||||||
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// Receive embedded XCM message within `ExportMessage` in Parachain destination
|
|
||||||
AssetHubWestend::execute_with(|| {
|
|
||||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
|
||||||
|
|
||||||
assert_expected_events!(
|
|
||||||
AssetHubWestend,
|
|
||||||
vec![
|
|
||||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed {
|
|
||||||
..
|
..
|
||||||
}) => {},
|
}) => {},
|
||||||
]
|
]
|
||||||
|
|||||||
+4
-33
@@ -16,7 +16,7 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn send_xcm_from_westend_relay_to_rococo_asset_hub() {
|
fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable() {
|
||||||
// Init tests variables
|
// Init tests variables
|
||||||
// XcmPallet send arguments
|
// XcmPallet send arguments
|
||||||
let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
|
let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
|
||||||
@@ -53,7 +53,8 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub() {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// Receive XCM message in Bridge Hub source Parachain
|
// Receive XCM message in Bridge Hub source Parachain, it should fail, because we don't have
|
||||||
|
// opened bridge/lane.
|
||||||
BridgeHubWestend::execute_with(|| {
|
BridgeHubWestend::execute_with(|| {
|
||||||
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
|
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
|
||||||
|
|
||||||
@@ -61,37 +62,7 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub() {
|
|||||||
BridgeHubWestend,
|
BridgeHubWestend,
|
||||||
vec![
|
vec![
|
||||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed {
|
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed {
|
||||||
success: true,
|
success: false,
|
||||||
..
|
|
||||||
}) => {},
|
|
||||||
RuntimeEvent::BridgeRococoMessages(pallet_bridge_messages::Event::MessageAccepted {
|
|
||||||
lane_id: LaneId([0, 0, 0, 2]),
|
|
||||||
nonce: 1,
|
|
||||||
}) => {},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Rococo Global Consensus
|
|
||||||
// Receive XCM message in Bridge Hub target Parachain
|
|
||||||
BridgeHubRococo::execute_with(|| {
|
|
||||||
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
|
|
||||||
|
|
||||||
assert_expected_events!(
|
|
||||||
BridgeHubRococo,
|
|
||||||
vec![
|
|
||||||
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// Receive embedded XCM message within `ExportMessage` in Parachain destination
|
|
||||||
AssetHubRococo::execute_with(|| {
|
|
||||||
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
|
|
||||||
|
|
||||||
assert_expected_events!(
|
|
||||||
AssetHubRococo,
|
|
||||||
vec![
|
|
||||||
RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed {
|
|
||||||
..
|
..
|
||||||
}) => {},
|
}) => {},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ pallet-bridge-grandpa = { path = "../../../../../bridges/modules/grandpa", defau
|
|||||||
pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false }
|
pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false }
|
||||||
pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false }
|
pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false }
|
||||||
pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false }
|
pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false }
|
||||||
|
pallet-xcm-bridge-hub = { path = "../../../../../bridges/modules/xcm-bridge-hub", default-features = false }
|
||||||
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false }
|
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -156,6 +157,7 @@ std = [
|
|||||||
"pallet-transaction-payment/std",
|
"pallet-transaction-payment/std",
|
||||||
"pallet-utility/std",
|
"pallet-utility/std",
|
||||||
"pallet-xcm-benchmarks?/std",
|
"pallet-xcm-benchmarks?/std",
|
||||||
|
"pallet-xcm-bridge-hub/std",
|
||||||
"pallet-xcm/std",
|
"pallet-xcm/std",
|
||||||
"parachain-info/std",
|
"parachain-info/std",
|
||||||
"parachains-common/std",
|
"parachains-common/std",
|
||||||
@@ -207,6 +209,7 @@ runtime-benchmarks = [
|
|||||||
"pallet-timestamp/runtime-benchmarks",
|
"pallet-timestamp/runtime-benchmarks",
|
||||||
"pallet-utility/runtime-benchmarks",
|
"pallet-utility/runtime-benchmarks",
|
||||||
"pallet-xcm-benchmarks/runtime-benchmarks",
|
"pallet-xcm-benchmarks/runtime-benchmarks",
|
||||||
|
"pallet-xcm-bridge-hub/runtime-benchmarks",
|
||||||
"pallet-xcm/runtime-benchmarks",
|
"pallet-xcm/runtime-benchmarks",
|
||||||
"parachains-common/runtime-benchmarks",
|
"parachains-common/runtime-benchmarks",
|
||||||
"polkadot-parachain-primitives/runtime-benchmarks",
|
"polkadot-parachain-primitives/runtime-benchmarks",
|
||||||
@@ -239,6 +242,7 @@ try-runtime = [
|
|||||||
"pallet-timestamp/try-runtime",
|
"pallet-timestamp/try-runtime",
|
||||||
"pallet-transaction-payment/try-runtime",
|
"pallet-transaction-payment/try-runtime",
|
||||||
"pallet-utility/try-runtime",
|
"pallet-utility/try-runtime",
|
||||||
|
"pallet-xcm-bridge-hub/try-runtime",
|
||||||
"pallet-xcm/try-runtime",
|
"pallet-xcm/try-runtime",
|
||||||
"parachain-info/try-runtime",
|
"parachain-info/try-runtime",
|
||||||
"polkadot-runtime-common/try-runtime",
|
"polkadot-runtime-common/try-runtime",
|
||||||
|
|||||||
+31
-19
@@ -18,8 +18,10 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bridge_common_config::{BridgeParachainWestendInstance, DeliveryRewardInBalance},
|
bridge_common_config::{BridgeParachainWestendInstance, DeliveryRewardInBalance},
|
||||||
weights, AccountId, BridgeWestendMessages, ParachainInfo, Runtime, RuntimeEvent, RuntimeOrigin,
|
weights,
|
||||||
XcmRouter,
|
xcm_config::UniversalLocation,
|
||||||
|
AccountId, BridgeWestendMessages, Runtime, RuntimeEvent, RuntimeOrigin,
|
||||||
|
XcmOverBridgeHubWestend, XcmRouter,
|
||||||
};
|
};
|
||||||
use bp_messages::LaneId;
|
use bp_messages::LaneId;
|
||||||
use bridge_runtime_common::{
|
use bridge_runtime_common::{
|
||||||
@@ -46,7 +48,7 @@ use xcm::{
|
|||||||
latest::prelude::*,
|
latest::prelude::*,
|
||||||
prelude::{InteriorMultiLocation, NetworkId},
|
prelude::{InteriorMultiLocation, NetworkId},
|
||||||
};
|
};
|
||||||
use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter};
|
use xcm_builder::BridgeBlobDispatcher;
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce =
|
pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce =
|
||||||
@@ -55,23 +57,28 @@ parameter_types! {
|
|||||||
bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||||
pub const BridgeHubWestendChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID;
|
pub const BridgeHubWestendChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID;
|
||||||
pub BridgeRococoToWestendMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(<BridgeWestendMessages as PalletInfoAccess>::index() as u8));
|
pub BridgeRococoToWestendMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(<BridgeWestendMessages as PalletInfoAccess>::index() as u8));
|
||||||
pub BridgeHubRococoUniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(Rococo), Parachain(ParachainInfo::parachain_id().into()));
|
|
||||||
pub WestendGlobalConsensusNetwork: NetworkId = NetworkId::Westend;
|
pub WestendGlobalConsensusNetwork: NetworkId = NetworkId::Westend;
|
||||||
pub ActiveOutboundLanesToBridgeHubWestend: &'static [bp_messages::LaneId] = &[XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND];
|
|
||||||
pub const AssetHubRococoToAssetHubWestendMessagesLane: bp_messages::LaneId = XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND;
|
|
||||||
// see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value
|
// see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value
|
||||||
pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;
|
pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;
|
||||||
|
|
||||||
pub AssetHubRococoParaId: cumulus_primitives_core::ParaId = bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID.into();
|
pub AssetHubRococoParaId: cumulus_primitives_core::ParaId = bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID.into();
|
||||||
pub AssetHubWestendParaId: cumulus_primitives_core::ParaId = bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID.into();
|
pub AssetHubWestendParaId: cumulus_primitives_core::ParaId = bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID.into();
|
||||||
|
|
||||||
|
// Lanes
|
||||||
|
pub ActiveOutboundLanesToBridgeHubWestend: &'static [bp_messages::LaneId] = &[XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND];
|
||||||
|
pub const AssetHubRococoToAssetHubWestendMessagesLane: bp_messages::LaneId = XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND;
|
||||||
pub FromAssetHubRococoToAssetHubWestendRoute: SenderAndLane = SenderAndLane::new(
|
pub FromAssetHubRococoToAssetHubWestendRoute: SenderAndLane = SenderAndLane::new(
|
||||||
ParentThen(X1(Parachain(AssetHubRococoParaId::get().into()))).into(),
|
ParentThen(X1(Parachain(AssetHubRococoParaId::get().into()))).into(),
|
||||||
XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND,
|
XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND,
|
||||||
);
|
);
|
||||||
|
pub ActiveLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![
|
||||||
|
(
|
||||||
|
FromAssetHubRococoToAssetHubWestendRoute::get(),
|
||||||
|
(WestendGlobalConsensusNetwork::get(), X1(Parachain(AssetHubWestendParaId::get().into())))
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
pub CongestedMessage: Xcm<()> = build_congestion_message(true).into();
|
pub CongestedMessage: Xcm<()> = build_congestion_message(true).into();
|
||||||
|
|
||||||
pub UncongestedMessage: Xcm<()> = build_congestion_message(false).into();
|
pub UncongestedMessage: Xcm<()> = build_congestion_message(false).into();
|
||||||
}
|
}
|
||||||
pub const XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND: LaneId = LaneId([0, 0, 0, 2]);
|
pub const XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND: LaneId = LaneId([0, 0, 0, 2]);
|
||||||
@@ -103,23 +110,16 @@ pub type ToWestendBridgeHubMessagesDeliveryProof =
|
|||||||
FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_westend::Hash>;
|
FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_westend::Hash>;
|
||||||
|
|
||||||
/// Dispatches received XCM messages from other bridge
|
/// Dispatches received XCM messages from other bridge
|
||||||
type FromWestendMessageBlobDispatcher = BridgeBlobDispatcher<
|
type FromWestendMessageBlobDispatcher =
|
||||||
XcmRouter,
|
BridgeBlobDispatcher<XcmRouter, UniversalLocation, BridgeRococoToWestendMessagesPalletInstance>;
|
||||||
BridgeHubRococoUniversalLocation,
|
|
||||||
BridgeRococoToWestendMessagesPalletInstance,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// Export XCM messages to be relayed to the other side
|
/// Export XCM messages to be relayed to the other side
|
||||||
pub type ToBridgeHubWestendHaulBlobExporter = HaulBlobExporter<
|
pub type ToBridgeHubWestendHaulBlobExporter = XcmOverBridgeHubWestend;
|
||||||
XcmBlobHaulerAdapter<ToBridgeHubWestendXcmBlobHauler>,
|
|
||||||
WestendGlobalConsensusNetwork,
|
|
||||||
(),
|
|
||||||
>;
|
|
||||||
pub struct ToBridgeHubWestendXcmBlobHauler;
|
pub struct ToBridgeHubWestendXcmBlobHauler;
|
||||||
impl XcmBlobHauler for ToBridgeHubWestendXcmBlobHauler {
|
impl XcmBlobHauler for ToBridgeHubWestendXcmBlobHauler {
|
||||||
type Runtime = Runtime;
|
type Runtime = Runtime;
|
||||||
type MessagesInstance = WithBridgeHubWestendMessagesInstance;
|
type MessagesInstance = WithBridgeHubWestendMessagesInstance;
|
||||||
type SenderAndLane = FromAssetHubRococoToAssetHubWestendRoute;
|
|
||||||
|
|
||||||
type ToSourceChainSender = XcmRouter;
|
type ToSourceChainSender = XcmRouter;
|
||||||
type CongestedMessage = CongestedMessage;
|
type CongestedMessage = CongestedMessage;
|
||||||
@@ -127,7 +127,8 @@ impl XcmBlobHauler for ToBridgeHubWestendXcmBlobHauler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On messages delivered callback.
|
/// On messages delivered callback.
|
||||||
type OnMessagesDeliveredFromWestend = XcmBlobHaulerAdapter<ToBridgeHubWestendXcmBlobHauler>;
|
type OnMessagesDeliveredFromWestend =
|
||||||
|
XcmBlobHaulerAdapter<ToBridgeHubWestendXcmBlobHauler, ActiveLanes>;
|
||||||
|
|
||||||
/// Messaging Bridge configuration for BridgeHubRococo -> BridgeHubWestend
|
/// Messaging Bridge configuration for BridgeHubRococo -> BridgeHubWestend
|
||||||
pub struct WithBridgeHubWestendMessageBridge;
|
pub struct WithBridgeHubWestendMessageBridge;
|
||||||
@@ -229,6 +230,17 @@ impl pallet_bridge_messages::Config<WithBridgeHubWestendMessagesInstance> for Ru
|
|||||||
type OnMessagesDelivered = OnMessagesDeliveredFromWestend;
|
type OnMessagesDelivered = OnMessagesDeliveredFromWestend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add support for the export and dispatch of XCM programs.
|
||||||
|
pub type XcmOverBridgeHubWestendInstance = pallet_xcm_bridge_hub::Instance1;
|
||||||
|
impl pallet_xcm_bridge_hub::Config<XcmOverBridgeHubWestendInstance> for Runtime {
|
||||||
|
type UniversalLocation = UniversalLocation;
|
||||||
|
type BridgedNetworkId = WestendGlobalConsensusNetwork;
|
||||||
|
type BridgeMessagesPalletInstance = WithBridgeHubWestendMessagesInstance;
|
||||||
|
type MessageExportPrice = ();
|
||||||
|
type Lanes = ActiveLanes;
|
||||||
|
type LanesSupport = ToBridgeHubWestendXcmBlobHauler;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -500,6 +500,8 @@ construct_runtime!(
|
|||||||
|
|
||||||
BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event<T>} = 47,
|
BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event<T>} = 47,
|
||||||
|
|
||||||
|
XcmOverBridgeHubWestend: pallet_xcm_bridge_hub::<Instance1>::{Pallet} = 52,
|
||||||
|
|
||||||
// Message Queue. Importantly, is registered last so that messages are processed after
|
// Message Queue. Importantly, is registered last so that messages are processed after
|
||||||
// the `on_initialize` hooks of bridging pallets.
|
// the `on_initialize` hooks of bridging pallets.
|
||||||
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 250,
|
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 250,
|
||||||
@@ -931,7 +933,13 @@ impl_runtime_apis! {
|
|||||||
|
|
||||||
fn export_message_origin_and_destination(
|
fn export_message_origin_and_destination(
|
||||||
) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> {
|
) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> {
|
||||||
Ok((TokenLocation::get(), NetworkId::Westend, X1(Parachain(100))))
|
Ok(
|
||||||
|
(
|
||||||
|
bridge_to_westend_config::FromAssetHubRococoToAssetHubWestendRoute::get().location,
|
||||||
|
NetworkId::Westend,
|
||||||
|
X1(Parachain(bridge_to_westend_config::AssetHubWestendParaId::get().into()))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> {
|
fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ mod bridge_hub_rococo_tests {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|| ExportMessage { network: Westend, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) },
|
|| ExportMessage { network: Westend, destination: X1(Parachain(bridge_to_westend_config::AssetHubWestendParaId::get().into())), xcm: Xcm(vec![]) },
|
||||||
XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND,
|
XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_ASSET_HUB_WESTEND,
|
||||||
Some((TokenLocation::get(), ExistentialDeposit::get()).into()),
|
Some((TokenLocation::get(), ExistentialDeposit::get()).into()),
|
||||||
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
|
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ parachain-info = { package = "staging-parachain-info", path = "../../../pallets/
|
|||||||
parachains-common = { path = "../../../common", default-features = false }
|
parachains-common = { path = "../../../common", default-features = false }
|
||||||
|
|
||||||
# Bridges
|
# Bridges
|
||||||
|
bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false }
|
||||||
bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false }
|
bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false }
|
||||||
bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false }
|
bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false }
|
||||||
bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false }
|
bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false }
|
||||||
@@ -89,6 +90,7 @@ pallet-bridge-grandpa = { path = "../../../../../bridges/modules/grandpa", defau
|
|||||||
pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false }
|
pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false }
|
||||||
pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false }
|
pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false }
|
||||||
pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false }
|
pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false }
|
||||||
|
pallet-xcm-bridge-hub = { path = "../../../../../bridges/modules/xcm-bridge-hub", default-features = false }
|
||||||
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false }
|
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -100,6 +102,7 @@ sp-keyring = { path = "../../../../../substrate/primitives/keyring" }
|
|||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = [
|
std = [
|
||||||
|
"bp-asset-hub-rococo/std",
|
||||||
"bp-asset-hub-westend/std",
|
"bp-asset-hub-westend/std",
|
||||||
"bp-bridge-hub-rococo/std",
|
"bp-bridge-hub-rococo/std",
|
||||||
"bp-bridge-hub-westend/std",
|
"bp-bridge-hub-westend/std",
|
||||||
@@ -144,6 +147,7 @@ std = [
|
|||||||
"pallet-transaction-payment/std",
|
"pallet-transaction-payment/std",
|
||||||
"pallet-utility/std",
|
"pallet-utility/std",
|
||||||
"pallet-xcm-benchmarks?/std",
|
"pallet-xcm-benchmarks?/std",
|
||||||
|
"pallet-xcm-bridge-hub/std",
|
||||||
"pallet-xcm/std",
|
"pallet-xcm/std",
|
||||||
"parachain-info/std",
|
"parachain-info/std",
|
||||||
"parachains-common/std",
|
"parachains-common/std",
|
||||||
@@ -195,6 +199,7 @@ runtime-benchmarks = [
|
|||||||
"pallet-timestamp/runtime-benchmarks",
|
"pallet-timestamp/runtime-benchmarks",
|
||||||
"pallet-utility/runtime-benchmarks",
|
"pallet-utility/runtime-benchmarks",
|
||||||
"pallet-xcm-benchmarks/runtime-benchmarks",
|
"pallet-xcm-benchmarks/runtime-benchmarks",
|
||||||
|
"pallet-xcm-bridge-hub/runtime-benchmarks",
|
||||||
"pallet-xcm/runtime-benchmarks",
|
"pallet-xcm/runtime-benchmarks",
|
||||||
"parachains-common/runtime-benchmarks",
|
"parachains-common/runtime-benchmarks",
|
||||||
"polkadot-parachain-primitives/runtime-benchmarks",
|
"polkadot-parachain-primitives/runtime-benchmarks",
|
||||||
@@ -227,6 +232,7 @@ try-runtime = [
|
|||||||
"pallet-timestamp/try-runtime",
|
"pallet-timestamp/try-runtime",
|
||||||
"pallet-transaction-payment/try-runtime",
|
"pallet-transaction-payment/try-runtime",
|
||||||
"pallet-utility/try-runtime",
|
"pallet-utility/try-runtime",
|
||||||
|
"pallet-xcm-bridge-hub/try-runtime",
|
||||||
"pallet-xcm/try-runtime",
|
"pallet-xcm/try-runtime",
|
||||||
"parachain-info/try-runtime",
|
"parachain-info/try-runtime",
|
||||||
"polkadot-runtime-common/try-runtime",
|
"polkadot-runtime-common/try-runtime",
|
||||||
|
|||||||
+30
-19
@@ -17,8 +17,9 @@
|
|||||||
//! Bridge definitions used on BridgeHub with the Westend flavor.
|
//! Bridge definitions used on BridgeHub with the Westend flavor.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bridge_common_config::DeliveryRewardInBalance, weights, AccountId, BridgeRococoMessages,
|
bridge_common_config::DeliveryRewardInBalance, weights, xcm_config::UniversalLocation,
|
||||||
ParachainInfo, Runtime, RuntimeEvent, RuntimeOrigin, XcmRouter,
|
AccountId, BridgeRococoMessages, Runtime, RuntimeEvent, RuntimeOrigin, XcmOverBridgeHubRococo,
|
||||||
|
XcmRouter,
|
||||||
};
|
};
|
||||||
use bp_messages::LaneId;
|
use bp_messages::LaneId;
|
||||||
use bp_parachains::SingleParaStoredHeaderDataBuilder;
|
use bp_parachains::SingleParaStoredHeaderDataBuilder;
|
||||||
@@ -48,7 +49,7 @@ use xcm::{
|
|||||||
latest::prelude::*,
|
latest::prelude::*,
|
||||||
prelude::{InteriorMultiLocation, NetworkId},
|
prelude::{InteriorMultiLocation, NetworkId},
|
||||||
};
|
};
|
||||||
use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter};
|
use xcm_builder::BridgeBlobDispatcher;
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
pub const RelayChainHeadersToKeep: u32 = 1024;
|
pub const RelayChainHeadersToKeep: u32 = 1024;
|
||||||
@@ -62,23 +63,29 @@ parameter_types! {
|
|||||||
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
|
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
|
||||||
bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
|
||||||
pub const BridgeHubRococoChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID;
|
pub const BridgeHubRococoChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID;
|
||||||
pub BridgeHubWestendUniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(Westend), Parachain(ParachainInfo::parachain_id().into()));
|
|
||||||
pub BridgeWestendToRococoMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(<BridgeRococoMessages as PalletInfoAccess>::index() as u8));
|
pub BridgeWestendToRococoMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(<BridgeRococoMessages as PalletInfoAccess>::index() as u8));
|
||||||
pub RococoGlobalConsensusNetwork: NetworkId = NetworkId::Rococo;
|
pub RococoGlobalConsensusNetwork: NetworkId = NetworkId::Rococo;
|
||||||
pub ActiveOutboundLanesToBridgeHubRococo: &'static [bp_messages::LaneId] = &[XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO];
|
|
||||||
pub const AssetHubWestendToAssetHubRococoMessagesLane: bp_messages::LaneId = XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO;
|
|
||||||
// see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value
|
// see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value
|
||||||
pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;
|
pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;
|
||||||
|
|
||||||
pub AssetHubWestendParaId: cumulus_primitives_core::ParaId = bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID.into();
|
pub AssetHubWestendParaId: cumulus_primitives_core::ParaId = bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID.into();
|
||||||
|
pub AssetHubRococoParaId: cumulus_primitives_core::ParaId = bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID.into();
|
||||||
|
|
||||||
|
// Lanes
|
||||||
|
pub ActiveOutboundLanesToBridgeHubRococo: &'static [bp_messages::LaneId] = &[XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO];
|
||||||
|
pub const AssetHubWestendToAssetHubRococoMessagesLane: bp_messages::LaneId = XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO;
|
||||||
pub FromAssetHubWestendToAssetHubRococoRoute: SenderAndLane = SenderAndLane::new(
|
pub FromAssetHubWestendToAssetHubRococoRoute: SenderAndLane = SenderAndLane::new(
|
||||||
ParentThen(X1(Parachain(AssetHubWestendParaId::get().into()))).into(),
|
ParentThen(X1(Parachain(AssetHubWestendParaId::get().into()))).into(),
|
||||||
XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO,
|
XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO,
|
||||||
);
|
);
|
||||||
|
pub ActiveLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![
|
||||||
|
(
|
||||||
|
FromAssetHubWestendToAssetHubRococoRoute::get(),
|
||||||
|
(RococoGlobalConsensusNetwork::get(), X1(Parachain(AssetHubRococoParaId::get().into())))
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
pub CongestedMessage: Xcm<()> = build_congestion_message(true).into();
|
pub CongestedMessage: Xcm<()> = build_congestion_message(true).into();
|
||||||
|
|
||||||
pub UncongestedMessage: Xcm<()> = build_congestion_message(false).into();
|
pub UncongestedMessage: Xcm<()> = build_congestion_message(false).into();
|
||||||
}
|
}
|
||||||
pub const XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO: LaneId = LaneId([0, 0, 0, 2]);
|
pub const XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO: LaneId = LaneId([0, 0, 0, 2]);
|
||||||
@@ -110,23 +117,16 @@ pub type ToRococoBridgeHubMessagesDeliveryProof =
|
|||||||
FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_rococo::Hash>;
|
FromBridgedChainMessagesDeliveryProof<bp_bridge_hub_rococo::Hash>;
|
||||||
|
|
||||||
/// Dispatches received XCM messages from other bridge
|
/// Dispatches received XCM messages from other bridge
|
||||||
type FromRococoMessageBlobDispatcher = BridgeBlobDispatcher<
|
type FromRococoMessageBlobDispatcher =
|
||||||
XcmRouter,
|
BridgeBlobDispatcher<XcmRouter, UniversalLocation, BridgeWestendToRococoMessagesPalletInstance>;
|
||||||
BridgeHubWestendUniversalLocation,
|
|
||||||
BridgeWestendToRococoMessagesPalletInstance,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// Export XCM messages to be relayed to the other side
|
/// Export XCM messages to be relayed to the other side
|
||||||
pub type ToBridgeHubRococoHaulBlobExporter = HaulBlobExporter<
|
pub type ToBridgeHubRococoHaulBlobExporter = XcmOverBridgeHubRococo;
|
||||||
XcmBlobHaulerAdapter<ToBridgeHubRococoXcmBlobHauler>,
|
|
||||||
RococoGlobalConsensusNetwork,
|
|
||||||
(),
|
|
||||||
>;
|
|
||||||
pub struct ToBridgeHubRococoXcmBlobHauler;
|
pub struct ToBridgeHubRococoXcmBlobHauler;
|
||||||
impl XcmBlobHauler for ToBridgeHubRococoXcmBlobHauler {
|
impl XcmBlobHauler for ToBridgeHubRococoXcmBlobHauler {
|
||||||
type Runtime = Runtime;
|
type Runtime = Runtime;
|
||||||
type MessagesInstance = WithBridgeHubRococoMessagesInstance;
|
type MessagesInstance = WithBridgeHubRococoMessagesInstance;
|
||||||
type SenderAndLane = FromAssetHubWestendToAssetHubRococoRoute;
|
|
||||||
|
|
||||||
type ToSourceChainSender = XcmRouter;
|
type ToSourceChainSender = XcmRouter;
|
||||||
type CongestedMessage = CongestedMessage;
|
type CongestedMessage = CongestedMessage;
|
||||||
@@ -134,7 +134,7 @@ impl XcmBlobHauler for ToBridgeHubRococoXcmBlobHauler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On messages delivered callback.
|
/// On messages delivered callback.
|
||||||
type OnMessagesDelivered = XcmBlobHaulerAdapter<ToBridgeHubRococoXcmBlobHauler>;
|
type OnMessagesDelivered = XcmBlobHaulerAdapter<ToBridgeHubRococoXcmBlobHauler, ActiveLanes>;
|
||||||
|
|
||||||
/// Messaging Bridge configuration for BridgeHubWestend -> BridgeHubRococo
|
/// Messaging Bridge configuration for BridgeHubWestend -> BridgeHubRococo
|
||||||
pub struct WithBridgeHubRococoMessageBridge;
|
pub struct WithBridgeHubRococoMessageBridge;
|
||||||
@@ -256,6 +256,17 @@ impl pallet_bridge_messages::Config<WithBridgeHubRococoMessagesInstance> for Run
|
|||||||
type OnMessagesDelivered = OnMessagesDelivered;
|
type OnMessagesDelivered = OnMessagesDelivered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add support for the export and dispatch of XCM programs.
|
||||||
|
pub type XcmOverBridgeHubRococoInstance = pallet_xcm_bridge_hub::Instance1;
|
||||||
|
impl pallet_xcm_bridge_hub::Config<XcmOverBridgeHubRococoInstance> for Runtime {
|
||||||
|
type UniversalLocation = UniversalLocation;
|
||||||
|
type BridgedNetworkId = RococoGlobalConsensusNetwork;
|
||||||
|
type BridgeMessagesPalletInstance = WithBridgeHubRococoMessagesInstance;
|
||||||
|
type MessageExportPrice = ();
|
||||||
|
type Lanes = ActiveLanes;
|
||||||
|
type LanesSupport = ToBridgeHubRococoXcmBlobHauler;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -488,6 +488,7 @@ construct_runtime!(
|
|||||||
BridgeRococoGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Storage, Event<T>, Config<T>} = 42,
|
BridgeRococoGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Storage, Event<T>, Config<T>} = 42,
|
||||||
BridgeRococoParachains: pallet_bridge_parachains::<Instance1>::{Pallet, Call, Storage, Event<T>} = 43,
|
BridgeRococoParachains: pallet_bridge_parachains::<Instance1>::{Pallet, Call, Storage, Event<T>} = 43,
|
||||||
BridgeRococoMessages: pallet_bridge_messages::<Instance1>::{Pallet, Call, Storage, Event<T>, Config<T>} = 44,
|
BridgeRococoMessages: pallet_bridge_messages::<Instance1>::{Pallet, Call, Storage, Event<T>, Config<T>} = 44,
|
||||||
|
XcmOverBridgeHubRococo: pallet_xcm_bridge_hub::<Instance1>::{Pallet} = 45,
|
||||||
|
|
||||||
// Message Queue. Importantly, is registered last so that messages are processed after
|
// Message Queue. Importantly, is registered last so that messages are processed after
|
||||||
// the `on_initialize` hooks of bridging pallets.
|
// the `on_initialize` hooks of bridging pallets.
|
||||||
@@ -921,7 +922,13 @@ impl_runtime_apis! {
|
|||||||
|
|
||||||
fn export_message_origin_and_destination(
|
fn export_message_origin_and_destination(
|
||||||
) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> {
|
) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> {
|
||||||
Ok((WestendLocation::get(), NetworkId::Rococo, X1(Parachain(100))))
|
Ok(
|
||||||
|
(
|
||||||
|
bridge_to_rococo_config::FromAssetHubWestendToAssetHubRococoRoute::get().location,
|
||||||
|
NetworkId::Rococo,
|
||||||
|
X1(Parachain(bridge_to_rococo_config::AssetHubRococoParaId::get().into()))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> {
|
fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> {
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|| ExportMessage { network: Rococo, destination: X1(Parachain(4321)), xcm: Xcm(vec![]) },
|
|| ExportMessage { network: Rococo, destination: X1(Parachain(bridge_to_rococo_config::AssetHubRococoParaId::get().into())), xcm: Xcm(vec![]) },
|
||||||
XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO,
|
XCM_LANE_FOR_ASSET_HUB_WESTEND_TO_ASSET_HUB_ROCOCO,
|
||||||
Some((WestendLocation::get(), ExistentialDeposit::get()).into()),
|
Some((WestendLocation::get(), ExistentialDeposit::get()).into()),
|
||||||
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
|
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
|
||||||
|
|||||||
@@ -1457,9 +1457,9 @@ pub mod test_data {
|
|||||||
);
|
);
|
||||||
// to compute proper cost of GRANDPA call, let's add some dummy bytes to header, so that the
|
// to compute proper cost of GRANDPA call, let's add some dummy bytes to header, so that the
|
||||||
// `submit_finality_proof` call size would be close to maximal expected (and refundable)
|
// `submit_finality_proof` call size would be close to maximal expected (and refundable)
|
||||||
let expected_bytes_in_grandpa_call = BridgedRelayChain::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION
|
let expected_bytes_in_grandpa_call = BridgedRelayChain::AVERAGE_HEADER_SIZE
|
||||||
.saturating_mul(BridgedRelayChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY)
|
.saturating_mul(BridgedRelayChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY)
|
||||||
.saturating_add(BridgedRelayChain::MAX_HEADER_SIZE)
|
.saturating_add(BridgedRelayChain::MAX_MANDATORY_HEADER_SIZE)
|
||||||
as usize;
|
as usize;
|
||||||
let extra_bytes_required =
|
let extra_bytes_required =
|
||||||
expected_bytes_in_grandpa_call.saturating_sub(relay_chain_header.encoded_size());
|
expected_bytes_in_grandpa_call.saturating_sub(relay_chain_header.encoded_size());
|
||||||
|
|||||||
Reference in New Issue
Block a user