Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Bridge hub kusama polkadot with dynamic fees #3001

Open
wants to merge 19 commits into
base: bridge-hub-kusama-polkadot
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
02e00e6
Squashed 'bridges/' changes from edf33a2c85..8f86ec78b7
bkontur Aug 10, 2023
4d60d09
Merge commit '02e00e6411c56bc44497bcd05104b17cdfdc0862' into bridge-h…
bkontur Aug 10, 2023
e5ac886
[dynfees] Rococo/Wococo does not need congestion and dynamic fees (fo…
bkontur Aug 11, 2023
76115f6
[dynfees] Implemented `XcmChannelStatusProvider` for `XcmpQueue`
bkontur Aug 11, 2023
ebc0ed1
Update to new version with dynamic fees
bkontur Aug 12, 2023
a701215
Test for calculating base delivery fee on BridgeHubs
bkontur Aug 14, 2023
3a5dfe2
Adjusted test `handle_export_message_from_system_parachain_to_outboun…
bkontur Aug 14, 2023
983eb8d
Disabled `UnpaidExecution` for system parachains
bkontur Aug 14, 2023
9daeb8b
Extended script for local run BHK/P
bkontur Aug 14, 2023
307654e
Added XcmBridgeHubRouterCall::report_bridge_status encodings for AHK/P
bkontur Aug 15, 2023
16ac9a1
Add impl for `CongestedMessage/UncongestedMessage` for BridgeHubs
bkontur Aug 15, 2023
a9b4637
Added const for `XcmBridgeHubRouterTransactCallMaxWeight`
bkontur Aug 15, 2023
4c5e054
Adjusted `require_max_weight` with XcmBridgeHubRouterTransactCallMaxW…
bkontur Aug 15, 2023
5931a57
Introduced base delivery fee constants
bkontur Aug 16, 2023
ad6f236
Congestion messages as Optional to turn on/off `supports_congestion_d…
bkontur Aug 16, 2023
47addc3
Fix for BHRo/Wo
bkontur Aug 16, 2023
7824adb
Added consts for base fee with sanity check
bkontur Aug 16, 2023
ca28825
Merge remote-tracking branch 'origin/bridge-hub-kusama-polkadot' into…
bkontur Aug 16, 2023
8e21f41
Merge remote-tracking branch 'origin/bridge-hub-kusama-polkadot' into…
bkontur Aug 17, 2023
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
42 changes: 42 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"bridges/modules/messages",
"bridges/modules/parachains",
"bridges/modules/relayers",
"bridges/modules/xcm-bridge-hub-router",
"client/cli",
"client/collator",
"client/consensus/aura",
Expand Down
8 changes: 8 additions & 0 deletions pallets/xcmp-queue/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ cumulus-primitives-core = { path = "../../primitives/core", default-features = f
# Optional import for benchmarking
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "master" }

# Bridges
bp-xcm-bridge-hub-router = { path = "../../bridges/primitives/xcm-bridge-hub-router", default-features = false, optional = true }

[dev-dependencies]

# Substrate
Expand Down Expand Up @@ -55,6 +58,7 @@ std = [
"sp-std/std",
"xcm-executor/std",
"xcm/std",
"bp-xcm-bridge-hub-router/std",
]

runtime-benchmarks = [
Expand All @@ -64,3 +68,7 @@ runtime-benchmarks = [
"xcm-builder/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]

bridging = [
"bp-xcm-bridge-hub-router",
]
111 changes: 111 additions & 0 deletions pallets/xcmp-queue/src/bridging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

Comment on lines +14 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// limitations under the License.
// limitations under the License.
#![cfg(feature = "bridging")]

use crate::pallet;
use cumulus_primitives_core::ParaId;
use frame_support::pallet_prelude::Get;

/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks
/// both `OutboundXcmpStatus` and `InboundXcmpStatus` for defined `ParaId` if any of those is
/// suspended.
pub struct InboundAndOutboundXcmpChannelCongestionStatusProvider<SiblingBridgeHubParaId, Runtime>(
sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>,
);
impl<SiblingBridgeHubParaId: Get<ParaId>, Runtime: crate::Config>
bp_xcm_bridge_hub_router::XcmChannelStatusProvider
for InboundAndOutboundXcmpChannelCongestionStatusProvider<SiblingBridgeHubParaId, Runtime>
{
fn is_congested() -> bool {
// if the outbound channel with recipient is suspended, it means that one of further
// bridge queues (e.g. bridge queue between two bridge hubs) is overloaded, so we shall
// take larger fee for our outbound messages
let sibling_bridge_hub_id: ParaId = SiblingBridgeHubParaId::get();
let outbound_channels = pallet::OutboundXcmpStatus::<Runtime>::get();
let outbound_channel =
outbound_channels.iter().find(|c| c.recipient == sibling_bridge_hub_id);
let is_outbound_channel_suspended =
outbound_channel.map(|c| c.is_suspended()).unwrap_or(false);
if is_outbound_channel_suspended {
return true
}

// if the inbound channel with recipient is suspended, it means that we are unable to
// receive congestion reports from the bridge hub. So we assume the bridge pipeline is
// congested too
let inbound_channels = pallet::InboundXcmpStatus::<Runtime>::get();
let inbound_channel = inbound_channels.iter().find(|c| c.sender == sibling_bridge_hub_id);
let is_inbound_channel_suspended =
inbound_channel.map(|c| c.is_suspended()).unwrap_or(false);
if is_inbound_channel_suspended {
return true
}

// TODO: https://github.com/paritytech/cumulus/pull/2342 - once this PR is merged, we may
// remove the following code
//
// if the outbound channel has at least `N` pages enqueued, let's assume it is congested.
// Normally, the chain with a few opened HRMP channels, will "send" pages at every block.
// Having `N` pages means that for last `N` blocks we either have not sent any messages,
// or have sent signals.
const MAX_OUTBOUND_PAGES_BEFORE_CONGESTION: u16 = 4;
let is_outbound_channel_congested = outbound_channel.map(|c| c.queued_pages()).unwrap_or(0);
is_outbound_channel_congested > MAX_OUTBOUND_PAGES_BEFORE_CONGESTION
}
}

/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks
/// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended.
pub struct OutboundXcmpChannelCongestionStatusProvider<SiblingBridgeHubParaId, Runtime>(
sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>,
);
impl<SiblingParaId: Get<ParaId>, Runtime: crate::Config>
bp_xcm_bridge_hub_router::XcmChannelStatusProvider
for OutboundXcmpChannelCongestionStatusProvider<SiblingParaId, Runtime>
{
fn is_congested() -> bool {
// let's find the channel with the sibling parachain
let sibling_para_id: cumulus_primitives_core::ParaId = SiblingParaId::get();
let outbound_channels = pallet::OutboundXcmpStatus::<Runtime>::get();
let channel_with_sibling_parachain =
outbound_channels.iter().find(|c| c.recipient == sibling_para_id);

// no channel => it is empty, so not congested
let channel_with_sibling_parachain = match channel_with_sibling_parachain {
Some(channel_with_sibling_parachain) => channel_with_sibling_parachain,
None => return false,
};

// suspended channel => it is congested
if channel_with_sibling_parachain.is_suspended() {
return true
}

// TODO: the following restriction is arguable, we may live without that, assuming that
// there can't be more than some `N` messages queued at the bridge queue (at the source BH)
// AND before accepting next (or next-after-next) delivery transaction, we'll receive the
// suspension signal from the target parachain and stop accepting delivery transactions

// it takes some time for target parachain to suspend inbound channel with the target BH and
// during that we will keep accepting new message delivery transactions. Let's also reject
// new deliveries if there are too many "pages" (concatenated XCM messages) in the target BH
// -> target parachain queue.
const MAX_QUEUED_PAGES_BEFORE_DEACTIVATION: u16 = 4;
if channel_with_sibling_parachain.queued_pages() > MAX_QUEUED_PAGES_BEFORE_DEACTIVATION {
return true
}

true
}
}
19 changes: 19 additions & 0 deletions pallets/xcmp-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
#[cfg(feature = "bridging")]
pub mod bridging;
pub mod weights;
pub use weights::WeightInfo;

Expand Down Expand Up @@ -400,6 +402,13 @@ pub struct InboundChannelDetails {
message_metadata: Vec<(RelayBlockNumber, XcmpMessageFormat)>,
}

impl InboundChannelDetails {
#[cfg(feature = "bridging")]
pub(crate) fn is_suspended(&self) -> bool {
self.state == InboundState::Suspended
}
}

/// Struct containing detailed information about the outbound channel.
#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
pub struct OutboundChannelDetails {
Expand Down Expand Up @@ -435,6 +444,16 @@ impl OutboundChannelDetails {
self.state = OutboundState::Suspended;
self
}

#[cfg(feature = "bridging")]
pub(crate) fn is_suspended(&self) -> bool {
self.state == OutboundState::Suspended
}

#[cfg(feature = "bridging")]
pub(crate) fn queued_pages(&self) -> u16 {
self.last_index.saturating_sub(self.first_index)
}
}

#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
Expand Down
2 changes: 2 additions & 0 deletions parachains/runtimes/bridge-hubs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ This initialization does several things:
- drips SA for AssetHubKusama on AssetHubPolkadot (and vice versa) which holds reserved assets on source chains
```
./scripts/bridges_kusama_polkadot.sh init-asset-hub-kusama-local
./scripts/bridges_kusama_polkadot.sh init-bridge-hub-kusama-local
./scripts/bridges_kusama_polkadot.sh init-asset-hub-polkadot-local
./scripts/bridges_kusama_polkadot.sh init-bridge-hub-polkadot-local
```

### 4. Send messages - transfer asset over bridge (DOTs/KSMs)
Expand Down
4 changes: 3 additions & 1 deletion parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea
cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false }
cumulus-pallet-session-benchmarking = {path = "../../../../pallets/session-benchmarking", default-features = false, version = "3.0.0"}
cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false }
cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] }
cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false }
cumulus-primitives-timestamp = { path = "../../../../primitives/timestamp", default-features = false }
cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false }
Expand All @@ -72,6 +72,7 @@ parachain-info = { path = "../../../../parachains/pallets/parachain-info", defau
parachains-common = { path = "../../../../parachains/common", default-features = false }

# Bridges
bp-asset-hub-kusama = { path = "../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false }
bp-bridge-hub-kusama = { path = "../../../../bridges/primitives/chain-bridge-hub-kusama", default-features = false }
bp-bridge-hub-polkadot = { path = "../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false }
bp-header-chain = { path = "../../../../bridges/primitives/header-chain", default-features = false }
Expand Down Expand Up @@ -99,6 +100,7 @@ default = [
"std",
]
std = [
"bp-asset-hub-kusama/std",
"bp-bridge-hub-kusama/std",
"bp-bridge-hub-polkadot/std",
"bp-header-chain/std",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use bridge_runtime_common::{
RefundableParachain,
},
};
use codec::Encode;
use frame_support::{parameter_types, traits::PalletInfoAccess, RuntimeDebug};
use xcm::{latest::prelude::*, prelude::NetworkId};
use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter};
Expand All @@ -54,6 +55,28 @@ parameter_types! {
ParentThen(X1(Parachain(AssetHubKusamaParaId::get().into()))).into(),
ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID,
);

pub CongestedMessage: Xcm<()> = sp_std::vec![Transact {
origin_kind: OriginKind::Xcm,
require_weight_at_most: bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(),
call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter(
bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status {
bridge_id: Default::default(),
is_congested: true,
}
).encode().into(),
}].into();

pub UncongestedMessage: Xcm<()> = sp_std::vec![Transact {
origin_kind: OriginKind::Xcm,
require_weight_at_most: bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(),
call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter(
bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status {
bridge_id: Default::default(),
is_congested: false,
}
).encode().into(),
}].into();
}

/// Proof of messages, coming from BridgeHubPolkadot.
Expand All @@ -80,10 +103,13 @@ impl XcmBlobHauler for ToBridgeHubPolkadotXcmBlobHauler {
type SenderAndLane = FromAssetHubKusamaToAssetHubPolkadotRoute;

type ToSourceChainSender = crate::XcmRouter;
type CongestedMessage = ();
type UncongestedMessage = ();
type CongestedMessage = CongestedMessage;
type UncongestedMessage = UncongestedMessage;
}

/// On messages delivered callback.
pub type OnMessagesDelivered = XcmBlobHaulerAdapter<ToBridgeHubPolkadotXcmBlobHauler>;

/// Messaging Bridge configuration for ThisChain -> BridgeHubPolkadot
pub struct WithBridgeHubPolkadotMessageBridge;
impl MessageBridge for WithBridgeHubPolkadotMessageBridge {
Expand Down
12 changes: 9 additions & 3 deletions parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,15 @@ impl pallet_bridge_messages::Config<WithBridgeHubPolkadotMessagesInstance> for R
DeliveryRewardInBalance,
>;
type SourceHeaderChain = SourceHeaderChainAdapter<WithBridgeHubPolkadotMessageBridge>;
type MessageDispatch =
XcmBlobMessageDispatch<OnThisChainBlobDispatcher<UniversalLocation>, Self::WeightInfo, ()>;
type OnMessagesDelivered = ();
type MessageDispatch = XcmBlobMessageDispatch<
OnThisChainBlobDispatcher<UniversalLocation>,
Self::WeightInfo,
cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider<
bridge_hub_config::AssetHubKusamaParaId,
Runtime,
>,
>;
type OnMessagesDelivered = bridge_hub_config::OnMessagesDelivered;
}

/// Allows collect and claim rewards for relayers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,6 @@ match_types! {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(_) }
};
// TODO:check-parameter - (https://github.com/paritytech/parity-bridges-common/issues/2084)
// remove this and extend `AllowExplicitUnpaidExecutionFrom` with "or SystemParachains" once merged https://github.com/paritytech/polkadot/pull/7005
pub type SystemParachains: impl Contains<MultiLocation> = {
// Statemine
MultiLocation { parents: 1, interior: X1(Parachain(1000)) }
};
}

/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly
Expand Down Expand Up @@ -191,9 +185,8 @@ pub type Barrier = TrailingSetTopicAsId<
// If the message is one that immediately attemps to pay for execution, then
// allow it.
AllowTopLevelPaidExecutionFrom<Everything>,
// Parent, its pluralities (i.e. governance bodies) and system parachains get
// free execution.
AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, SystemParachains)>,
// Parent and its pluralities (i.e. governance bodies) get free execution.
bkontur marked this conversation as resolved.
Show resolved Hide resolved
AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality,)>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentOrSiblings>,
),
Expand Down
Loading