Skip to content

Commit

Permalink
Extended Kusama/Polkadot BridgeHub with dynamic fees and congestion s…
Browse files Browse the repository at this point in the history
…upport

Add congestion detection to the Bridge Hub runtimes and report congestion status to the sending chain.

Bridge Hub's `ExportMessage` handling is extended with check if outbound message queue is congested,
if so then `CongestedMessage` signal is sent to the sending chain's relevant `pallet-xcm-bridge-hub-router` pallet instance,
where dynamic fees factor is processed.
When then same Bridge Hub receives message delivery confirmation, there is a another check is outbound queue is still congested,
if not then `UncongestedMessage` signal is sent to the sending chain's relevant `pallet-xcm-bridge-hub-router` pallet instance.

`pallet-bridge-messages`'s `receive_messages_proof` does another check for congestion or back-preassure
with checking status of underlaying XCMP queue (`cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider`).
If we cannot deliver a message to the target, then `receive_messages_proof` returns error and Bridge Hub does not allow to receive new bridged messages.

More about congestion detection [here](paritytech/parity-bridges-common#2318).

Signed-off-by: Branislav Kontur <bkontur@gmail.com>
Signed-off-by: Adrian Catangiu <adrian@parity.io>
Signed-off-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
Signed-off-by: Serban Iorga <serban@parity.io>

Co-authored-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
Co-authored-by: Serban Iorga <serban@parity.io>
  • Loading branch information
4 people authored and claravanstaden committed Sep 19, 2023
1 parent 92a75db commit 9777608
Show file tree
Hide file tree
Showing 15 changed files with 299 additions and 53 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion cumulus/pallets/xcmp-queue/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ cumulus-pallet-parachain-system = { path = "../parachain-system" }
[features]
default = [ "std" ]
std = [
"bp-xcm-bridge-hub-router/std",
"bp-xcm-bridge-hub-router?/std",
"codec/std",
"cumulus-primitives-core/std",
"frame-benchmarking?/std",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea
cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] }
cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false}
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-utility = { path = "../../../../primitives/utility", default-features = false }
pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false }
parachain-info = { path = "../../../pallets/parachain-info", default-features = false }
parachains-common = { path = "../../../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 All @@ -97,6 +98,7 @@ sp-keyring = { path = "../../../../../substrate/primitives/keyring" }
[features]
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};
use sp_runtime::RuntimeDebug;
use xcm::{latest::prelude::*, prelude::NetworkId};
Expand All @@ -55,6 +56,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 @@ -81,10 +104,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
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,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 Expand Up @@ -942,7 +948,11 @@ impl_runtime_apis! {
type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;

use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_parachain, prepare_message_proof_from_parachain};
use bridge_runtime_common::messages_benchmarking::{
generate_xcm_builder_bridge_message_sample,
prepare_message_delivery_proof_from_parachain,
prepare_message_proof_from_parachain
};
use pallet_bridge_messages::benchmarking::{
Config as BridgeMessagesConfig,
Pallet as BridgeMessagesBench,
Expand Down Expand Up @@ -972,7 +982,7 @@ impl_runtime_apis! {
Runtime,
BridgeGrandpaPolkadotInstance,
bridge_hub_config::WithBridgeHubPolkadotMessageBridge,
>(params, X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42)))
>(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42))))
}
fn prepare_message_delivery_proof(
params: MessageDeliveryProofParams<AccountId>,
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.
AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality,)>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentOrSiblings>,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use bp_polkadot_core::Signature;
pub use bridge_hub_kusama_runtime::{
bridge_hub_config,
xcm_config::{RelayNetwork, XcmConfig},
xcm_config::{KsmRelayLocation, RelayNetwork, XcmConfig},
AllPalletsWithoutSystem, Balances, BridgeGrandpaPolkadotInstance,
BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm,
Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubPolkadotMessagesInstance,
Expand Down Expand Up @@ -183,7 +183,10 @@ fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() {
}
}),
|| ExportMessage { network: Polkadot, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) },
bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID
bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID,
Some((KsmRelayLocation::get(), ExistentialDeposit::get()).into()),
// value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer`
Some((KsmRelayLocation::get(), bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get()).into()),
)
}

Expand Down Expand Up @@ -262,3 +265,21 @@ pub fn complex_relay_extrinsic_works() {
construct_and_apply_extrinsic,
);
}

#[test]
pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() {
let estimated = bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::<
Runtime,
XcmConfig,
WeightToFee,
>();

// check if estimated value is sane
let max_expected = bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get();
assert!(
estimated <= max_expected,
"calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots` value",
estimated,
max_expected
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea
cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] }
cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false}
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-utility = { path = "../../../../primitives/utility", default-features = false }
pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false }
parachain-info = { path = "../../../pallets/parachain-info", default-features = false }
parachains-common = { path = "../../../common", default-features = false }

# Bridges
bp-asset-hub-polkadot = { path = "../../../../bridges/primitives/chain-asset-hub-polkadot", 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 All @@ -97,6 +98,7 @@ sp-keyring = { path = "../../../../../substrate/primitives/keyring" }
[features]
default = [ "std" ]
std = [
"bp-asset-hub-polkadot/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};
use sp_runtime::RuntimeDebug;
use xcm::{latest::prelude::*, prelude::NetworkId};
Expand All @@ -55,6 +56,28 @@ parameter_types! {
ParentThen(X1(Parachain(AssetHubPolkadotParaId::get().into()))).into(),
ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID,
);

pub CongestedMessage: Xcm<()> = sp_std::vec![Transact {
origin_kind: OriginKind::Xcm,
require_weight_at_most: bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(),
call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter(
bp_asset_hub_polkadot::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_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(),
call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter(
bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status {
bridge_id: Default::default(),
is_congested: false,
}
).encode().into(),
}].into();
}

/// Proof of messages, coming from BridgeHubKusama.
Expand All @@ -81,10 +104,13 @@ impl XcmBlobHauler for ToBridgeHubKusamaXcmBlobHauler {
type SenderAndLane = FromAssetHubPolkadotToAssetHubKusamaRoute;

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

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

/// Messaging Bridge configuration for ThisChain -> BridgeHubKusama
pub struct WithBridgeHubKusamaMessageBridge;
impl MessageBridge for WithBridgeHubKusamaMessageBridge {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,9 +494,15 @@ impl pallet_bridge_messages::Config<WithBridgeHubKusamaMessagesInstance> for Run
DeliveryRewardInBalance,
>;
type SourceHeaderChain = SourceHeaderChainAdapter<WithBridgeHubKusamaMessageBridge>;
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::AssetHubPolkadotParaId,
Runtime,
>,
>;
type OnMessagesDelivered = bridge_hub_config::OnMessagesDelivered;
}

/// Allows collect and claim rewards for relayers
Expand Down Expand Up @@ -943,7 +949,11 @@ impl_runtime_apis! {
type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>;

use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_parachain, prepare_message_proof_from_parachain};
use bridge_runtime_common::messages_benchmarking::{
generate_xcm_builder_bridge_message_sample,
prepare_message_delivery_proof_from_parachain,
prepare_message_proof_from_parachain
};
use pallet_bridge_messages::benchmarking::{
Config as BridgeMessagesConfig,
Pallet as BridgeMessagesBench,
Expand Down Expand Up @@ -973,7 +983,7 @@ impl_runtime_apis! {
Runtime,
BridgeGrandpaKusamaInstance,
bridge_hub_config::WithBridgeHubKusamaMessageBridge,
>(params, X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42)))
>(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42))))
}
fn prepare_message_delivery_proof(
params: MessageDeliveryProofParams<AccountId>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,6 @@ match_types! {
pub type FellowsPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: X2(Parachain(1001), Plurality { id: BodyId::Technical, ..}) }
};
// 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> = {
// Statemint
MultiLocation { parents: 1, interior: X1(Parachain(1000)) } |
// Collectives
MultiLocation { parents: 1, interior: X1(Parachain(1001)) }
};
}

/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly
Expand Down Expand Up @@ -196,13 +188,9 @@ 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), the Fellows plurality
// and system parachains get free execution.
AllowExplicitUnpaidExecutionFrom<(
ParentOrParentsPlurality,
FellowsPlurality,
SystemParachains,
)>,
// Parent, its pluralities (i.e. governance bodies) and the Fellows plurality
// get free execution.
AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, FellowsPlurality)>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<ParentOrSiblings>,
),
Expand Down
Loading

0 comments on commit 9777608

Please sign in to comment.