Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 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 bridges/primitives/chain-bridge-hub-rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub const WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers";

/// Pallet index of `BridgeWestendMessages: pallet_bridge_messages::<Instance3>`.
pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 51;
/// Pallet index of `BridgePolkadotBulletinMessages: pallet_bridge_messages::<Instance4>`.
pub const WITH_BRIDGE_ROCOCO_TO_BULLETIN_MESSAGES_PALLET_INDEX: u8 = 53;

decl_bridge_finality_runtime_apis!(bridge_hub_rococo);
decl_bridge_messages_runtime_apis!(bridge_hub_rococo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ parachains-common = { path = "../../../common", default-features = false }
# Bridges
bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hub-rococo", default-features = false }
bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false }
bp-bridge-hub-polkadot = { path = "../../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false }
bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false }
bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false }
bp-header-chain = { path = "../../../../../bridges/primitives/header-chain", default-features = false }
bp-messages = { path = "../../../../../bridges/primitives/messages", default-features = false }
bp-parachains = { path = "../../../../../bridges/primitives/parachains", default-features = false }
bp-polkadot-bulletin = { path = "../../../../../bridges/primitives/chain-polkadot-bulletin", default-features = false }
bp-polkadot-core = { path = "../../../../../bridges/primitives/polkadot-core", default-features = false }
bp-relayers = { path = "../../../../../bridges/primitives/relayers", default-features = false }
bp-runtime = { path = "../../../../../bridges/primitives/runtime", default-features = false }
Expand All @@ -113,11 +115,13 @@ default = [ "std" ]
std = [
"bp-asset-hub-rococo/std",
"bp-asset-hub-westend/std",
"bp-bridge-hub-polkadot/std",
"bp-bridge-hub-rococo/std",
"bp-bridge-hub-westend/std",
"bp-header-chain/std",
"bp-messages/std",
"bp-parachains/std",
"bp-polkadot-bulletin/std",
"bp-polkadot-core/std",
"bp-relayers/std",
"bp-rococo/std",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,34 @@
//! For example, the messaging pallet needs to know the sending and receiving chains, but the
//! GRANDPA tracking pallet only needs to be aware of one chain.

use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent};
use super::{
weights, AccountId, Balance, Balances, BlockNumber, ParachainInfo, Runtime, RuntimeEvent,
RuntimeOrigin,
};
use bp_parachains::SingleParaStoredHeaderDataBuilder;
use bp_runtime::UnderlyingChainProvider;
use bridge_runtime_common::messages::ThisChainWithMessages;
use frame_support::{parameter_types, traits::ConstU32};
use sp_runtime::RuntimeDebug;
use xcm::latest::prelude::*;

parameter_types! {
pub const RelayChainHeadersToKeep: u32 = 1024;
pub const ParachainHeadsToKeep: u32 = 64;

pub const WestendBridgeParachainPalletName: &'static str = "Paras";
pub const WestendBridgeParachainPalletName: &'static str = bp_westend::PARAS_PALLET_NAME;
pub const MaxWestendParaHeadDataSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE;

pub storage RequiredStakeForStakeAndSlash: Balance = 1_000_000;
pub const RelayerStakeLease: u32 = 8;
pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs";

pub storage DeliveryRewardInBalance: u64 = 1_000_000;

pub BridgeHubRococoUniversalLocation: InteriorMultiLocation = X2(
GlobalConsensus(Rococo),
Parachain(ParachainInfo::parachain_id().into()),
);
}

/// Add GRANDPA bridge pallet to track Westend relay chain.
Expand Down Expand Up @@ -78,3 +90,33 @@ impl pallet_bridge_relayers::Config for Runtime {
>;
type WeightInfo = weights::pallet_bridge_relayers::WeightInfo<Runtime>;
}

/// Add GRANDPA bridge pallet to track Rococo Bulletin chain.
pub type BridgeGrandpaRococoBulletinInstance = pallet_bridge_grandpa::Instance4;
impl pallet_bridge_grandpa::Config<BridgeGrandpaRococoBulletinInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type BridgedChain = bp_polkadot_bulletin::PolkadotBulletin;
type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>;
type HeadersToKeep = RelayChainHeadersToKeep;
// Technically this is incorrect - we have two pallet instances and ideally we shall
// benchmark every instance separately. But the benchmarking engine has a flaw - it
// messes with components. E.g. in Kusama maximal validators count is 1024 and in
// Bulletin chain it is 100. But benchmarking engine runs Bulletin benchmarks using
// components range, computed for Kusama => it causes an error.
//
// In practice, however, GRANDPA pallet works the same way for all bridged chains, so
// weights are also the same for both bridges.
type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo<Runtime>;
}

/// BridgeHubRococo chain from message lane point of view.
#[derive(RuntimeDebug, Clone, Copy)]
pub struct BridgeHubRococo;

impl UnderlyingChainProvider for BridgeHubRococo {
type Chain = bp_bridge_hub_rococo::BridgeHubRococo;
}

impl ThisChainWithMessages for BridgeHubRococo {
type RuntimeOrigin = RuntimeOrigin;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Cumulus.

// Cumulus 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.

// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.

//! Bridge definitions used on BridgeHubRococo for bridging to Rococo Bulletin.
//!
//! Rococo Bulletin chain will be the 1:1 copy of the Polkadot Bulletin, so we
//! are reusing Polkadot Bulletin chain primitives everywhere here.

use crate::{
bridge_common_config::{
BridgeGrandpaRococoBulletinInstance, BridgeHubRococo, BridgeHubRococoUniversalLocation,
},
weights, AccountId, BridgeRococoBulletinGrandpa, BridgeRococoBulletinMessages, Runtime,
RuntimeEvent, XcmRouter,
};
use bp_messages::LaneId;
use bridge_runtime_common::{
messages,
messages::{
source::{FromBridgedChainMessagesDeliveryProof, TargetHeaderChainAdapter},
target::{FromBridgedChainMessagesProof, SourceHeaderChainAdapter},
MessageBridge, UnderlyingChainProvider,
},
messages_xcm_extension::{
SenderAndLane, XcmAsPlainPayload, XcmBlobHauler, XcmBlobHaulerAdapter,
XcmBlobMessageDispatch,
},
refund_relayer_extension::{
ActualFeeRefund, RefundBridgedGrandpaMessages, RefundSignedExtensionAdapter,
RefundableMessagesLane,
},
};

use frame_support::{parameter_types, traits::PalletInfoAccess};
use sp_runtime::RuntimeDebug;
use xcm::{
latest::prelude::*,
prelude::{InteriorMultiLocation, NetworkId},
};
use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter};

parameter_types! {
/// Maximal number of entries in the unrewarded relayers vector at the Rococo Bridge Hub. It matches the
/// maximal number of unrewarded relayers that the single confirmation transaction at Rococo Bulletin Chain
/// may process.
pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce =
bp_polkadot_bulletin::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
/// Maximal number of unconfirmed messages at the Rococo Bridge Hub. It matches the maximal number of
/// uncinfirmed messages that the single confirmation transaction at Rococo Bulletin Chain may process.
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
bp_polkadot_bulletin::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
/// Bridge specific chain (network) identifier of the Rococo Bulletin Chain.
pub const RococoBulletinChainId: bp_runtime::ChainId = bp_runtime::POLKADOT_BULLETIN_CHAIN_ID;
/// Interior location (relative to this runtime) of the with-RococoBulletin messages pallet.
pub BridgeRococoToRococoBulletinMessagesPalletInstance: InteriorMultiLocation = X1(
PalletInstance(<BridgeRococoBulletinMessages as PalletInfoAccess>::index() as u8)
);
/// Rococo Bulletin Network identifier.
pub RococoBulletinGlobalConsensusNetwork: NetworkId = NetworkId::PolkadotBulletin;
/// All active lanes that the current bridge supports.
pub ActiveOutboundLanesToRococoBulletin: &'static [bp_messages::LaneId]
= &[XCM_LANE_FOR_ROCOCO_PEOPLE_TO_ROCOCO_BULLETIN];
/// Lane identifier, used to connect Rococo People and Rococo Bulletin chain.
pub const RococoPeopleToRococoBulletinMessagesLane: bp_messages::LaneId
= XCM_LANE_FOR_ROCOCO_PEOPLE_TO_ROCOCO_BULLETIN;
/// Priority boost that the registered relayer receives for every additional message in the message
/// delivery transaction.
///
/// It is determined semi-automatically - see `FEE_BOOST_PER_MESSAGE` constant to get the
/// meaning of this value.
pub PriorityBoostPerMessage: u64 = 182_044_444_444_444;

/// Identifier of the sibling Rococo People parachain.
pub RococoPeopleParaId: cumulus_primitives_core::ParaId = 1004.into();
/// A route (XCM location and bridge lane) that the Rococo People Chain -> Rococo Bulletin Chain
/// message is following.
pub FromRococoPeopleToRococoBulletinRoute: SenderAndLane = SenderAndLane::new(
ParentThen(X1(Parachain(RococoPeopleParaId::get().into()))).into(),
XCM_LANE_FOR_ROCOCO_PEOPLE_TO_ROCOCO_BULLETIN,
);

/// XCM message that is never sent.
pub NeverSentMessage: Option<Xcm<()>> = None;
}
pub const XCM_LANE_FOR_ROCOCO_PEOPLE_TO_ROCOCO_BULLETIN: LaneId = LaneId([0, 0, 0, 0]);

/// Proof of messages, coming from Rococo Bulletin chain.
pub type FromRococoBulletinMessagesProof =
FromBridgedChainMessagesProof<bp_polkadot_bulletin::Hash>;
/// Messages delivery proof for Rococo Bridge Hub -> Rococo Bulletin messages.
pub type ToRococoBulletinMessagesDeliveryProof =
FromBridgedChainMessagesDeliveryProof<bp_polkadot_bulletin::Hash>;

/// Dispatches received XCM messages from other bridge.
type FromRococoBulletinMessageBlobDispatcher = BridgeBlobDispatcher<
XcmRouter,
BridgeHubRococoUniversalLocation,
BridgeRococoToRococoBulletinMessagesPalletInstance,
>;

/// Export XCM messages to be relayed to the other side.
pub type ToRococoBulletinHaulBlobExporter = HaulBlobExporter<
XcmBlobHaulerAdapter<ToRococoBulletinXcmBlobHauler>,
RococoBulletinGlobalConsensusNetwork,
(),
>;
pub struct ToRococoBulletinXcmBlobHauler;
impl XcmBlobHauler for ToRococoBulletinXcmBlobHauler {
type Runtime = Runtime;
type MessagesInstance = WithRococoBulletinMessagesInstance;
type SenderAndLane = FromRococoPeopleToRococoBulletinRoute;

type ToSourceChainSender = XcmRouter;
type CongestedMessage = NeverSentMessage;
type UncongestedMessage = NeverSentMessage;
}

/// Messaging Bridge configuration for BridgeHubRococo -> Rococo Bulletin.
pub struct WithRococoBulletinMessageBridge;
impl MessageBridge for WithRococoBulletinMessageBridge {
// Bulletin chain assumes it is bridged with Polkadot Bridge Hub
const BRIDGED_MESSAGES_PALLET_NAME: &'static str =
bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME;
type ThisChain = BridgeHubRococo;
type BridgedChain = RococoBulletin;
type BridgedHeaderChain = BridgeRococoBulletinGrandpa;
}

/// Message verifier for RococoBulletin messages sent from BridgeHubRococo.
pub type ToRococoBulletinMessageVerifier =
messages::source::FromThisChainMessageVerifier<WithRococoBulletinMessageBridge>;

/// Maximal outbound payload size of BridgeHubRococo -> RococoBulletin messages.
pub type ToRococoBulletinMaximalOutboundPayloadSize =
messages::source::FromThisChainMaximalOutboundPayloadSize<WithRococoBulletinMessageBridge>;

/// RococoBulletin chain from message lane point of view.
#[derive(RuntimeDebug, Clone, Copy)]
pub struct RococoBulletin;

impl UnderlyingChainProvider for RococoBulletin {
type Chain = bp_polkadot_bulletin::PolkadotBulletin;
}

impl messages::BridgedChainWithMessages for RococoBulletin {}

/// Signed extension that refunds relayers that are delivering messages from the Rococo Bulletin
/// chain.
pub type OnBridgeHubRococoRefundRococoBulletinMessages = RefundSignedExtensionAdapter<
RefundBridgedGrandpaMessages<
Runtime,
BridgeGrandpaRococoBulletinInstance,
RefundableMessagesLane<
WithRococoBulletinMessagesInstance,
RococoPeopleToRococoBulletinMessagesLane,
>,
ActualFeeRefund<Runtime>,
PriorityBoostPerMessage,
StrOnBridgeHubRococoRefundRococoBulletinMessages,
>,
>;
bp_runtime::generate_static_str_provider!(OnBridgeHubRococoRefundRococoBulletinMessages);

/// Add XCM messages support for BridgeHubRococo to support Rococo->Rococo Bulletin XCM messages.
pub type WithRococoBulletinMessagesInstance = pallet_bridge_messages::Instance4;
impl pallet_bridge_messages::Config<WithRococoBulletinMessagesInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo =
weights::pallet_bridge_messages_rococo_to_rococo_bulletin::WeightInfo<Runtime>;
type BridgedChainId = RococoBulletinChainId;
type ActiveOutboundLanes = ActiveOutboundLanesToRococoBulletin;
type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane;
type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane;

type MaximalOutboundPayloadSize = ToRococoBulletinMaximalOutboundPayloadSize;
type OutboundPayload = XcmAsPlainPayload;

type InboundPayload = XcmAsPlainPayload;
type InboundRelayer = AccountId;
type DeliveryPayments = ();

type TargetHeaderChain = TargetHeaderChainAdapter<WithRococoBulletinMessageBridge>;
type LaneMessageVerifier = ToRococoBulletinMessageVerifier;
type DeliveryConfirmationPayments = ();

type SourceHeaderChain = SourceHeaderChainAdapter<WithRococoBulletinMessageBridge>;
type MessageDispatch =
XcmBlobMessageDispatch<FromRococoBulletinMessageBlobDispatcher, Self::WeightInfo, ()>;
type OnMessagesDelivered = ();
}

#[cfg(test)]
mod tests {
use super::*;
use crate::bridge_common_config::BridgeGrandpaRococoBulletinInstance;
use bridge_runtime_common::{
assert_complete_bridge_types, integrity::check_message_lane_weights,
};
use parachains_common::{rococo, Balance};

/// Every additional message in the message delivery transaction boosts its priority.
/// So the priority of transaction with `N+1` messages is larger than priority of
/// transaction with `N` messages by the `PriorityBoostPerMessage`.
///
/// Economically, it is an equivalent of adding tip to the transaction with `N` messages.
/// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip.
///
/// We want this tip to be large enough (delivery transactions with more messages = less
/// operational costs and a faster bridge), so this value should be significant.
const FEE_BOOST_PER_MESSAGE: Balance = 2 * rococo::currency::UNITS;

#[test]
fn ensure_bridge_hub_rococo_message_lane_weights_are_correct() {
check_message_lane_weights::<
bp_bridge_hub_rococo::BridgeHubRococo,
Runtime,
WithRococoBulletinMessagesInstance,
>(
bp_polkadot_bulletin::EXTRA_STORAGE_PROOF_SIZE,
bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
true,
);
}

#[test]
fn ensure_bridge_integrity() {
assert_complete_bridge_types!(
runtime: Runtime,
with_bridged_chain_grandpa_instance: BridgeGrandpaRococoBulletinInstance,
with_bridged_chain_messages_instance: WithRococoBulletinMessagesInstance,
bridge: WithRococoBulletinMessageBridge,
this_chain: bp_rococo::Rococo,
bridged_chain: bp_polkadot_bulletin::PolkadotBulletin,
);

// we can't use `assert_complete_bridge_constants` here, because there's a trick with
// Bulletin chain - it has the same (almost) runtime for Polkadot Bulletin and Rococo
// Bulletin, so we have to adhere Polkadot names here

bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::<
Runtime,
WithRococoBulletinMessagesInstance,
PriorityBoostPerMessage,
>(FEE_BOOST_PER_MESSAGE);

assert_eq!(
BridgeRococoToRococoBulletinMessagesPalletInstance::get(),
X1(PalletInstance(
bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_BULLETIN_MESSAGES_PALLET_INDEX
))
);
}
}
Loading