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

(PoC) XcmpQueue congestion support and dynamic fees #5831

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
10 changes: 9 additions & 1 deletion 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ members = [
"bridges/primitives/test-utils",
"bridges/primitives/xcm-bridge-hub",
"bridges/primitives/xcm-bridge-hub-router",
"bridges/primitives/xcm-bridge-support",
"bridges/relays/client-substrate",
"bridges/relays/equivocation",
"bridges/relays/finality",
Expand Down Expand Up @@ -649,6 +650,7 @@ bp-test-utils = { path = "bridges/primitives/test-utils", default-features = fal
bp-westend = { path = "bridges/chains/chain-westend", default-features = false }
bp-xcm-bridge-hub = { path = "bridges/primitives/xcm-bridge-hub", default-features = false }
bp-xcm-bridge-hub-router = { path = "bridges/primitives/xcm-bridge-hub-router", default-features = false }
bp-xcm-bridge-support = { path = "bridges/primitives/xcm-bridge-support", default-features = false }
bridge-hub-common = { path = "cumulus/parachains/runtimes/bridge-hubs/common", default-features = false }
bridge-hub-rococo-emulated-chain = { path = "cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo" }
bridge-hub-rococo-runtime = { path = "cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion bridges/modules/xcm-bridge-hub/src/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{Config, Pallet, LOG_TARGET};

use bp_messages::target_chain::{DispatchMessage, MessageDispatch};
use bp_runtime::messages::MessageDispatchResult;
use bp_xcm_bridge_hub::{LocalXcmChannelManager, XcmAsPlainPayload};
use bp_xcm_bridge_hub::{XcmAsPlainPayload, XcmChannelStatusProvider};
use codec::{Decode, Encode};
use frame_support::{weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound};
use pallet_bridge_messages::{Config as BridgeMessagesConfig, WeightInfoExt};
Expand Down
10 changes: 3 additions & 7 deletions bridges/modules/xcm-bridge-hub/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,6 @@ impl TestLocalXcmChannelManager {
impl LocalXcmChannelManager for TestLocalXcmChannelManager {
type Error = ();

fn is_congested(_with: &Location) -> bool {
frame_support::storage::unhashed::get_or_default(b"TestLocalXcmChannelManager.Congested")
}

fn suspend_bridge(_local_origin: &Location, _bridge: BridgeId) -> Result<(), Self::Error> {
frame_support::storage::unhashed::put(b"TestLocalXcmChannelManager.Suspended", &true);
Ok(())
Expand All @@ -430,9 +426,9 @@ impl LocalXcmChannelManager for TestLocalXcmChannelManager {
}
}

impl pallet_xcm_bridge_hub_router::XcmChannelStatusProvider for TestLocalXcmChannelManager {
fn is_congested(with: &Location) -> bool {
<Self as LocalXcmChannelManager>::is_congested(with)
impl bp_xcm_bridge_hub::XcmChannelStatusProvider for TestLocalXcmChannelManager {
fn is_congested(_with: &Location) -> bool {
frame_support::storage::unhashed::get_or_default(b"TestLocalXcmChannelManager.Congested")
}
}

Expand Down
7 changes: 3 additions & 4 deletions bridges/primitives/xcm-bridge-hub-router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,18 @@ workspace = true
codec = { features = ["bit-vec", "derive"], workspace = true }
scale-info = { features = ["bit-vec", "derive"], workspace = true }

# Bridge Dependencies
bp-xcm-bridge-support = { workspace = true }

# Substrate Dependencies
sp-runtime = { workspace = true }
sp-core = { workspace = true }

# Polkadot Dependencies
xcm = { workspace = true }

[features]
default = ["std"]
std = [
"codec/std",
"scale-info/std",
"sp-core/std",
"sp-runtime/std",
"xcm/std",
]
17 changes: 1 addition & 16 deletions bridges/primitives/xcm-bridge-hub-router/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,15 @@

#![cfg_attr(not(feature = "std"), no_std)]

pub use bp_xcm_bridge_support::XcmChannelStatusProvider;
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::H256;
use sp_runtime::{FixedU128, RuntimeDebug};
use xcm::latest::prelude::Location;

/// Minimal delivery fee factor.
pub const MINIMAL_DELIVERY_FEE_FACTOR: FixedU128 = FixedU128::from_u32(1);

/// XCM channel status provider that may report whether it is congested or not.
///
/// By channel we mean the physical channel that is used to deliver messages of one
/// of the bridge queues.
pub trait XcmChannelStatusProvider {
/// Returns true if the channel is currently congested.
fn is_congested(with: &Location) -> bool;
}

impl XcmChannelStatusProvider for () {
fn is_congested(_with: &Location) -> bool {
false
}
}

/// Current status of the bridge.
#[derive(Clone, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen, RuntimeDebug)]
pub struct BridgeState {
Expand Down
1 change: 1 addition & 0 deletions bridges/primitives/xcm-bridge-hub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ serde = { features = ["alloc", "derive"], workspace = true }
# Bridge Dependencies
bp-messages = { workspace = true }
bp-runtime = { workspace = true }
bp-xcm-bridge-support = { workspace = true }

# Substrate Dependencies
sp-std = { workspace = true }
Expand Down
13 changes: 2 additions & 11 deletions bridges/primitives/xcm-bridge-hub/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

use bp_messages::LaneIdType;
use bp_runtime::{AccountIdOf, BalanceOf, Chain};
pub use bp_xcm_bridge_support::XcmChannelStatusProvider;
pub use call_info::XcmBridgeHubCall;
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{
Expand Down Expand Up @@ -96,16 +97,10 @@ impl core::fmt::Debug for BridgeId {
}

/// Local XCM channel manager.
pub trait LocalXcmChannelManager {
pub trait LocalXcmChannelManager: bp_xcm_bridge_support::XcmChannelStatusProvider {
/// Error that may be returned when suspending/resuming the bridge.
type Error: sp_std::fmt::Debug;

/// Returns true if the channel with given location is currently congested.
///
/// The `with` is guaranteed to be in the same consensus. However, it may point to something
/// below the chain level - like the contract or pallet instance, for example.
fn is_congested(with: &Location) -> bool;

/// Suspend the bridge, opened by given origin.
///
/// The `local_origin` is guaranteed to be in the same consensus. However, it may point to
Expand All @@ -122,10 +117,6 @@ pub trait LocalXcmChannelManager {
impl LocalXcmChannelManager for () {
type Error = ();

fn is_congested(_with: &Location) -> bool {
false
}

fn suspend_bridge(_local_origin: &Location, _bridge: BridgeId) -> Result<(), Self::Error> {
Ok(())
}
Expand Down
21 changes: 21 additions & 0 deletions bridges/primitives/xcm-bridge-support/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "bp-xcm-bridge-support"
description = "Primitives for the xcm-like bridge."
version = "0.6.0"
authors.workspace = true
edition.workspace = true
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
repository.workspace = true

[lints]
workspace = true

[dependencies]
# Polkadot Dependencies
xcm = { workspace = true }

[features]
default = ["std"]
std = [
"xcm/std",
]
39 changes: 39 additions & 0 deletions bridges/primitives/xcm-bridge-support/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (C) 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 for the xcm-like bridge.

#![cfg_attr(not(feature = "std"), no_std)]

use xcm::latest::prelude::Location;

/// XCM channel status provider that may report whether it is congested or not.
///
/// By channel, we mean the physical channel that is used to deliver messages to/of one
/// of the bridge queues.
pub trait XcmChannelStatusProvider {
/// Returns true if the channel with given location is currently congested.
///
/// The `with` is guaranteed to be in the same consensus. However, it may point to something
/// below the chain level - like the contract or pallet instance, for example.
fn is_congested(with: &Location) -> bool;
}

impl XcmChannelStatusProvider for () {
fn is_congested(_with: &Location) -> bool {
false
}
}
6 changes: 3 additions & 3 deletions cumulus/pallets/xcmp-queue/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ frame-benchmarking = { optional = true, workspace = true }
bounded-collections = { workspace = true }

# Bridges
bp-xcm-bridge-hub-router = { optional = true, workspace = true }
bp-xcm-bridge-hub = { optional = true, workspace = true }

[dev-dependencies]

Expand All @@ -53,7 +53,7 @@ cumulus-pallet-parachain-system = { workspace = true, default-features = true }
default = ["std"]
std = [
"bounded-collections/std",
"bp-xcm-bridge-hub-router?/std",
"bp-xcm-bridge-hub?/std",
"codec/std",
"cumulus-primitives-core/std",
"frame-benchmarking?/std",
Expand Down Expand Up @@ -96,4 +96,4 @@ try-runtime = [
"polkadot-runtime-parachains/try-runtime",
"sp-runtime/try-runtime",
]
bridging = ["bp-xcm-bridge-hub-router"]
bridging = ["bp-xcm-bridge-hub"]
64 changes: 59 additions & 5 deletions cumulus/pallets/xcmp-queue/src/bridging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{pallet, OutboundState};
use crate::{pallet, ChannelSignal, OutboundState, LOG_TARGET};
use cumulus_primitives_core::ParaId;
use xcm::latest::prelude::*;

/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks
/// Adapter implementation for `XcmChannelStatusProvider` which checks
/// both `OutboundXcmpStatus` and `InboundXcmpStatus` for defined `Location` if any of those is
/// suspended.
pub struct InAndOutXcmpChannelStatusProvider<Runtime>(core::marker::PhantomData<Runtime>);
impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider
impl<Runtime: crate::Config> bp_xcm_bridge_hub::XcmChannelStatusProvider
for InAndOutXcmpChannelStatusProvider<Runtime>
{
fn is_congested(with: &Location) -> bool {
Expand All @@ -45,10 +45,64 @@ impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider
}
}

/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks
impl<Runtime: crate::Config> bp_xcm_bridge_hub::LocalXcmChannelManager
for InAndOutXcmpChannelStatusProvider<Runtime>
{
type Error = ();
fn suspend_bridge(with: &Location, _: bp_xcm_bridge_hub::BridgeId) -> Result<(), Self::Error> {
// handle congestion only for a sibling parachain locations.
let sibling_para_id: ParaId = match with.unpack() {
(_, [Parachain(para_id)]) => (*para_id).into(),
loc @ _ =>
return {
log::trace!(
target: LOG_TARGET,
"Unhandled location with: {loc:?}"
);
Ok(())
},
};

// report congestion = true
pallet::Pallet::<Runtime>::send_signal(sibling_para_id, ChannelSignal::ReportCongestion(true))
.map_err(|e| {
log::error!(
target: LOG_TARGET,
"Failed to send_signal(ReportCongestion(true)) to the sibling_para_id: `{sibling_para_id:?}` with error: {e:?}"
);
()
})
}
fn resume_bridge(with: &Location, _: bp_xcm_bridge_hub::BridgeId) -> Result<(), Self::Error> {
// handle congestion only for a sibling parachain locations.
let sibling_para_id: ParaId = match with.unpack() {
(_, [Parachain(para_id)]) => (*para_id).into(),
loc @ _ =>
return {
log::trace!(
target: LOG_TARGET,
"Unhandled location with: {loc:?}"
);
Ok(())
},
};

// report congestion = false
pallet::Pallet::<Runtime>::send_signal(sibling_para_id, ChannelSignal::ReportCongestion(false))
.map_err(|e| {
log::error!(
target: LOG_TARGET,
"Failed to send_signal(ReportCongestion(false)) to the sibling_para_id: `{sibling_para_id:?}` with error: {e:?}"
);
()
})
}
}

/// Adapter implementation for `XcmChannelStatusProvider` which checks
/// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended.
pub struct OutXcmpChannelStatusProvider<Runtime>(core::marker::PhantomData<Runtime>);
impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider
impl<Runtime: crate::Config> bp_xcm_bridge_hub::XcmChannelStatusProvider
for OutXcmpChannelStatusProvider<Runtime>
{
fn is_congested(with: &Location) -> bool {
Expand Down
Loading
Loading