From d630f5068fdbf21ea9ca90fa8ccbb35e203e0520 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 Jul 2023 17:57:56 +0300 Subject: [PATCH] introduce partial bp-xcm-bridge-hub - just LocalXcmChannelManager (#2265) --- Cargo.lock | 1 + bridges/primitives/xcm-bridge-hub/Cargo.toml | 8 ++- bridges/primitives/xcm-bridge-hub/src/lib.rs | 57 +++++++++++++++++++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce41401163e6..9304d9ce5215 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1925,6 +1925,7 @@ name = "bp-xcm-bridge-hub" version = "0.2.0" dependencies = [ "sp-std 14.0.0", + "staging-xcm", ] [[package]] diff --git a/bridges/primitives/xcm-bridge-hub/Cargo.toml b/bridges/primitives/xcm-bridge-hub/Cargo.toml index 27881bc99d1f..288bbd9af69a 100644 --- a/bridges/primitives/xcm-bridge-hub/Cargo.toml +++ b/bridges/primitives/xcm-bridge-hub/Cargo.toml @@ -15,6 +15,12 @@ workspace = true # Substrate Dependencies sp-std = { path = "../../../substrate/primitives/std", default-features = false } +# Polkadot Dependencies +xcm = { package = "staging-xcm", path = "../../../polkadot/xcm", default-features = false } + [features] default = ["std"] -std = ["sp-std/std"] +std = [ + "sp-std/std", + "xcm/std", +] diff --git a/bridges/primitives/xcm-bridge-hub/src/lib.rs b/bridges/primitives/xcm-bridge-hub/src/lib.rs index 9745011c902d..78f913273370 100644 --- a/bridges/primitives/xcm-bridge-hub/src/lib.rs +++ b/bridges/primitives/xcm-bridge-hub/src/lib.rs @@ -16,9 +16,64 @@ //! Primitives of the xcm-bridge-hub pallet. -#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +use xcm::latest::prelude::*; + /// 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; + +/// A manager of XCM communication channels between the bridge hub and parent/sibling chains +/// that have opened bridges at this bridge hub. +/// +/// We use this interface to suspend and resume channels programmatically to implement backpressure +/// mechanism for bridge queues. +#[allow(clippy::result_unit_err)] // XCM uses `Result<(), ()>` everywhere +pub trait LocalXcmChannelManager { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2255 + // check following assumptions. They are important at least for following cases: + // 1) we now close the associated outbound lane when misbehavior is reported. If we'll keep + // handling inbound XCM messages after the `suspend_inbound_channel`, they will be dropped + // 2) the sender will be able to enqueue message to othe lanes if we won't stop handling inbound + // XCM immediately. He even may open additional bridges + + /// Stop handling new incoming XCM messages from given bridge `owner` (parent/sibling chain). + /// + /// We assume that the channel will be suspended immediately, but we don't mind if inbound + /// messages will keep piling up here for some time. Once this is communicated to the + /// `owner` chain (in any form), we expect it to stop sending messages to us and queue + /// messages at that `owner` chain instead. + /// + /// This method will be called if we detect a misbehavior in one of bridges, owned by + /// the `owner`. We expect that: + /// + /// - no more incoming XCM messages from the `owner` will be processed until further + /// `resume_inbound_channel` call; + /// + /// - soon after the call, the channel will switch to the state when incoming messages are + /// piling up at the sending chain, not at the bridge hub. + /// + /// This method shall not fail if the channel is already suspended. + fn suspend_inbound_channel(owner: Location) -> Result<(), ()>; + + /// Start handling incoming messages from from given bridge `owner` (parent/sibling chain) + /// again. + /// + /// This method is called when the `owner` tries to resume bridge operations after + /// resolving "misbehavior" issues. The channel is assumed to be suspended by the previous + /// `suspend_inbound_channel` call, however we don't check it anywhere. + /// + /// This method shall not fail if the channel is already resumed. + fn resume_inbound_channel(owner: Location) -> Result<(), ()>; +} + +impl LocalXcmChannelManager for () { + fn suspend_inbound_channel(_owner: Location) -> Result<(), ()> { + Ok(()) + } + + fn resume_inbound_channel(_owner: Location) -> Result<(), ()> { + Err(()) + } +}