Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved ExportXcm::validate implementation for BridgeHubs - step 1 #2727

Merged
merged 5 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bin/runtime-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ bp-parachains = { path = "../../primitives/parachains", default-features = false
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
bp-relayers = { path = "../../primitives/relayers", 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 }
pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../modules/messages", default-features = false }
Expand Down Expand Up @@ -58,6 +59,7 @@ std = [
"bp-polkadot-core/std",
"bp-relayers/std",
"bp-runtime/std",
"bp-xcm-bridge-hub/std",
"bp-xcm-bridge-hub-router/std",
"codec/std",
"frame-support/std",
Expand Down
109 changes: 46 additions & 63 deletions bin/runtime-common/src/messages_xcm_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,23 @@
//! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue`
use bp_messages::{
source_chain::{MessagesBridge, OnMessagesDelivered},
source_chain::OnMessagesDelivered,
target_chain::{DispatchMessage, MessageDispatch},
LaneId, MessageNonce,
};
use bp_runtime::messages::MessageDispatchResult;
pub use bp_xcm_bridge_hub::XcmAsPlainPayload;
use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
use codec::{Decode, Encode};
use frame_support::{traits::Get, weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound};
use pallet_bridge_messages::{
Config as MessagesConfig, OutboundLanesCongestedSignals, Pallet as MessagesPallet,
WeightInfoExt as MessagesPalletWeights,
Config as MessagesConfig, OutboundLanesCongestedSignals, WeightInfoExt as MessagesPalletWeights,
};
use scale_info::TypeInfo;
use sp_runtime::SaturatedConversion;
use sp_std::{fmt::Debug, marker::PhantomData};
use xcm::prelude::*;
use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError};

/// Plain "XCM" payload, which we transfer through bridge
pub type XcmAsPlainPayload = sp_std::prelude::Vec<u8>;
use xcm_builder::{DispatchBlob, DispatchBlobError};

/// Message dispatch result type for single message
#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
Expand Down Expand Up @@ -123,6 +120,7 @@ impl<

/// A pair of sending chain location and message lane, used by this chain to send messages
/// over the bridge.
#[cfg_attr(feature = "std", derive(Debug, Eq, PartialEq))]
pub struct SenderAndLane {
/// Sending chain relative location.
pub location: MultiLocation,
Expand All @@ -144,8 +142,6 @@ pub trait XcmBlobHauler {
type Runtime: MessagesConfig<Self::MessagesInstance>;
/// Instance of the messages pallet that is used to send messages.
type MessagesInstance: 'static;
/// Returns lane used by this hauler.
type SenderAndLane: Get<SenderAndLane>;

/// Actual XCM message sender (`HRMP` or `UMP`) to the source chain
/// location (`Self::SenderAndLane::get().location`).
Expand All @@ -166,54 +162,25 @@ pub trait XcmBlobHauler {
/// makes sure that XCM blob is sent to the outbound lane to be relayed.
///
/// 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>
where
H::Runtime: MessagesConfig<H::MessagesInstance, OutboundPayload = XcmAsPlainPayload>,
impl<
H: XcmBlobHauler,
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) {
let sender_and_lane = H::SenderAndLane::get();
if sender_and_lane.lane != lane {
return
if let Some(sender_and_lane) =
Lanes::get().iter().find(|link| link.0.lane == lane).map(|link| &link.0)
{
// 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,
);
}
}

Expand Down Expand Up @@ -356,6 +323,9 @@ mod tests {
location: MultiLocation::new(1, X1(Parachain(1000))),
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();
}

Expand Down Expand Up @@ -389,56 +359,69 @@ mod tests {
impl XcmBlobHauler for TestBlobHauler {
type Runtime = TestRuntime;
type MessagesInstance = ();
type SenderAndLane = TestSenderAndLane;

type ToSourceChainSender = DummySendXcm;
type CongestedMessage = 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(
TEST_LANE_ID,
OutboundLaneData {
oldest_unpruned_nonce: 0,
latest_received_nonce: 0,
latest_generated_nonce: OUTBOUND_LANE_CONGESTED_THRESHOLD,
latest_generated_nonce,
},
);
latest_generated_nonce
}

#[test]
fn congested_signal_is_not_sent_twice() {
run_test(|| {
fill_up_lane_to_congestion();
let enqueued = fill_up_lane_to_congestion();

// 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);

// 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);
});
}

#[test]
fn congested_signal_is_not_sent_when_outbound_lane_is_not_congested() {
run_test(|| {
TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap();
LocalXcmQueueManager::<TestBlobHauler>::on_bridge_message_enqueued(
&TestSenderAndLane::get(),
1,
);
assert_eq!(DummySendXcm::messages_sent(), 0);
});
}

#[test]
fn congested_signal_is_sent_when_outbound_lane_is_congested() {
run_test(|| {
fill_up_lane_to_congestion();
let enqueued = fill_up_lane_to_congestion();

// 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!(LocalXcmQueueManager::<TestBlobHauler>::is_congested_signal_sent(TEST_LANE_ID));
});
Expand Down
74 changes: 74 additions & 0 deletions modules/xcm-bridge-hub/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }

# Polkadot Dependencies
xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }
xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }
xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false }

[dev-dependencies]
bp-header-chain = { path = "../../primitives/header-chain" }
pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" }
sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" }

[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",
]
Loading