Add Rococo People <> Rococo Bulletin bridge support to Rococo Bridge Hub (#2540)

This PR adds [Rococo
People](https://github.com/paritytech/polkadot-sdk/pull/2281) <> [Rococo
Bulletin](https://github.com/zdave-parity/polkadot-bulletin-chain) to
the Rococo Bridge Hub code. There's a couple of things left to do here:
- [x] add remaining tests - it'd need some refactoring in the
`bridge-hub-test-utils` - will do in a separate PR;
- [x] actually run benchmarks for new messaging pallet (do we have bot
nowadays?).

The reason why I'm opening it before this ^^^ is ready, is that I'd like
to hear others opinion on how to deal with hacks with that bridge.
Initially I was assuming that Rococo Bulletin will be the 1:1 copy of
the Polkadot Bulletin (to avoid maintaining multiple
runtimes/releases/...), so you can see many `PolkadotBulletin` mentions
in this PR, even though we are going to bridge with the parallel chain
(`RococoBulletin`). That's because e.g. pallet names from
`construct_runtime` are affecting runtime storage keys and bridges are
using runtime storage proofs => it is important to use names that the
Bulletin chain expects.

But in the end, this hack won't work - we can't use Polkadot Bulletin
runtime to bridge with Rococo Bridge Hub, because Polkadot Bulletin
expects Polkadot Bridge hub to use `1002` parachain id and Rococo Bridge
Hub seats on the `1013`. This also affects storage keys using in
bridging, so I had to add the [`rococo`
feature](https://github.com/svyatonik/polkadot-bulletin-chain/blob/add-bridge-pallets/runtime/Cargo.toml#L198)
to the Bulletin chain. So now we can actually alter its runtime and
adapt it for Rococo.

So the question here is - what's better for us here
- to leave everything as is (seems hacky and non-trivial);
- change Bulletin chain runtime when `rococo` feature is used - e.g. use
proper names there (`WithPolkadotGrandpa` -> `WithRococoGrandpa`, ...)
- add another set of pallets to the Bulletin chain runtime to bridge
with Rococo and never use them in production. Similar to hack that we
had in Rococo/Wococo

cc @acatangiu @bkontur @serban300 

also cc @joepetrowski as the main "client" of this bridge

---

A couple words on how this bridge is different from the Rococo <>
Westend bridge:
- it is a bridge with a chain that uses GRANDPA finality, not the
parachain finality (hence the tests needs to be changed);
- it is a fee-free bridge. So
`AllowExplicitUnpaidExecutionFrom<Equals<SiblingPeople>>` + we are not
paying any rewards to relayers (apart from compensating transaction
costs).

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com>
Co-authored-by: Egor_P <egor@parity.io>
Co-authored-by: command-bot <>
This commit is contained in:
Svyatoslav Nikolsky
2023-12-14 17:54:26 +03:00
committed by GitHub
parent 10a91f821e
commit 097308e385
14 changed files with 1002 additions and 124 deletions
@@ -18,6 +18,7 @@
//!
//! This runtime currently supports bridging between:
//! - Rococo <> Westend
//! - Rococo <> Rococo Bulletin
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
@@ -28,6 +29,7 @@
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod bridge_common_config;
pub mod bridge_to_bulletin_config;
pub mod bridge_to_westend_config;
mod weights;
pub mod xcm_config;
@@ -106,7 +108,10 @@ pub type SignedExtra = (
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
BridgeRejectObsoleteHeadersAndMessages,
(bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages,),
(
bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages,
bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages,
),
);
/// Unchecked extrinsic type as expected by this runtime.
@@ -483,39 +488,56 @@ construct_runtime!(
Utility: pallet_utility::{Pallet, Call, Event} = 40,
Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 36,
// BridgeHubRococo uses:
// - BridgeWestendGrandpa
// - BridgeWestendParachains
// - BridgeWestendMessages
// - BridgeRelayers
// GRANDPA bridge modules.
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance3>::{Pallet, Call, Storage, Event<T>, Config<T>} = 48,
// Parachain bridge modules.
BridgeWestendParachains: pallet_bridge_parachains::<Instance3>::{Pallet, Call, Storage, Event<T>} = 49,
// Messaging bridge modules.
BridgeWestendMessages: pallet_bridge_messages::<Instance3>::{Pallet, Call, Storage, Event<T>, Config<T>} = 51,
// Bridge relayers pallet, used by several bridges here.
BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event<T>} = 47,
// With-Westend GRANDPA bridge module.
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance3>::{Pallet, Call, Storage, Event<T>, Config<T>} = 48,
// With-Westend parachain bridge module.
BridgeWestendParachains: pallet_bridge_parachains::<Instance3>::{Pallet, Call, Storage, Event<T>} = 49,
// With-Westend messaging bridge module.
BridgeWestendMessages: pallet_bridge_messages::<Instance3>::{Pallet, Call, Storage, Event<T>, Config<T>} = 51,
// With-Westend bridge hub pallet.
XcmOverBridgeHubWestend: pallet_xcm_bridge_hub::<Instance1>::{Pallet} = 52,
// With-Rococo Bulletin GRANDPA bridge module.
//
// we can't use `BridgeRococoBulletinGrandpa` name here, because the same Bulletin runtime will be
// used for both Rococo and Polkadot Bulletin chains AND this name affects runtime storage keys, used
// by the relayer process
BridgePolkadotBulletinGrandpa: pallet_bridge_grandpa::<Instance4>::{Pallet, Call, Storage, Event<T>, Config<T>} = 60,
// With-Rococo Bulletin messaging bridge module.
//
// we can't use `BridgeRococoBulletinMessages` name here, because the same Bulletin runtime will be
// used for both Rococo and Polkadot Bulletin chains AND this name affects runtime storage keys, used
// by this runtime and the relayer process
BridgePolkadotBulletinMessages: pallet_bridge_messages::<Instance4>::{Pallet, Call, Storage, Event<T>, Config<T>} = 61,
// With-Rococo Bulletin bridge hub pallet.
XcmOverPolkadotBulletin: pallet_xcm_bridge_hub::<Instance2>::{Pallet} = 62,
// Message Queue. Importantly, is registered last so that messages are processed after
// the `on_initialize` hooks of bridging pallets.
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 250,
}
);
/// Proper alias for bridge GRANDPA pallet used to bridge with the bulletin chain.
pub type BridgeRococoBulletinGrandpa = BridgePolkadotBulletinGrandpa;
/// Proper alias for bridge messages pallet used to bridge with the bulletin chain.
pub type BridgeRococoBulletinMessages = BridgePolkadotBulletinMessages;
/// Proper alias for bridge messages pallet used to bridge with the bulletin chain.
pub type XcmOverRococoBulletin = XcmOverPolkadotBulletin;
bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! {
RuntimeCall, AccountId,
// Grandpa
BridgeWestendGrandpa,
BridgeRococoBulletinGrandpa,
// Parachains
BridgeWestendParachains,
// Messages
BridgeWestendMessages
BridgeWestendMessages,
BridgeRococoBulletinMessages
}
#[cfg(feature = "runtime-benchmarks")]
@@ -540,6 +562,7 @@ mod benches {
[pallet_bridge_grandpa, WestendFinality]
[pallet_bridge_parachains, WithinWestend]
[pallet_bridge_messages, RococoToWestend]
[pallet_bridge_messages, RococoToRococoBulletin]
[pallet_bridge_relayers, BridgeRelayersBench::<Runtime>]
);
}
@@ -733,6 +756,42 @@ impl_runtime_apis! {
}
}
impl bp_polkadot_bulletin::PolkadotBulletinFinalityApi<Block> for Runtime {
fn best_finalized() -> Option<bp_runtime::HeaderId<bp_polkadot_bulletin::Hash, bp_polkadot_bulletin::BlockNumber>> {
BridgePolkadotBulletinGrandpa::best_finalized()
}
fn synced_headers_grandpa_info(
) -> Vec<bp_header_chain::StoredHeaderGrandpaInfo<bp_polkadot_bulletin::Header>> {
BridgePolkadotBulletinGrandpa::synced_headers_grandpa_info()
}
}
impl bp_polkadot_bulletin::FromPolkadotBulletinInboundLaneApi<Block> for Runtime {
fn message_details(
lane: bp_messages::LaneId,
messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>,
) -> Vec<bp_messages::InboundMessageDetails> {
bridge_runtime_common::messages_api::inbound_message_details::<
Runtime,
bridge_to_bulletin_config::WithRococoBulletinMessagesInstance,
>(lane, messages)
}
}
impl bp_polkadot_bulletin::ToPolkadotBulletinOutboundLaneApi<Block> for Runtime {
fn message_details(
lane: bp_messages::LaneId,
begin: bp_messages::MessageNonce,
end: bp_messages::MessageNonce,
) -> Vec<bp_messages::OutboundMessageDetails> {
bridge_runtime_common::messages_api::outbound_message_details::<
Runtime,
bridge_to_bulletin_config::WithRococoBulletinMessagesInstance,
>(lane, begin, end)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
@@ -775,6 +834,7 @@ impl_runtime_apis! {
type WestendFinality = BridgeWestendGrandpa;
type WithinWestend = pallet_bridge_parachains::benchmarking::Pallet::<Runtime, bridge_common_config::BridgeParachainWestendInstance>;
type RococoToWestend = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>;
type RococoToRococoBulletin = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_bulletin_config::WithRococoBulletinMessagesInstance>;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
@@ -968,9 +1028,12 @@ impl_runtime_apis! {
type WestendFinality = BridgeWestendGrandpa;
type WithinWestend = pallet_bridge_parachains::benchmarking::Pallet::<Runtime, bridge_common_config::BridgeParachainWestendInstance>;
type RococoToWestend = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_westend_config::WithBridgeHubWestendMessagesInstance>;
type RococoToRococoBulletin = pallet_bridge_messages::benchmarking::Pallet ::<Runtime, bridge_to_bulletin_config::WithRococoBulletinMessagesInstance>;
use bridge_runtime_common::messages_benchmarking::{
prepare_message_delivery_proof_from_grandpa_chain,
prepare_message_delivery_proof_from_parachain,
prepare_message_proof_from_grandpa_chain,
prepare_message_proof_from_parachain,
generate_xcm_builder_bridge_message_sample,
};
@@ -1023,6 +1086,41 @@ impl_runtime_apis! {
}
}
impl BridgeMessagesConfig<bridge_to_bulletin_config::WithRococoBulletinMessagesInstance> for Runtime {
fn is_relayer_rewarded(_relayer: &Self::AccountId) -> bool {
// we do not pay any rewards in this bridge
true
}
fn prepare_message_proof(
params: MessageProofParams,
) -> (bridge_to_bulletin_config::FromRococoBulletinMessagesProof, Weight) {
use cumulus_primitives_core::XcmpMessageSource;
assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty());
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into());
prepare_message_proof_from_grandpa_chain::<
Runtime,
bridge_common_config::BridgeGrandpaRococoBulletinInstance,
bridge_to_bulletin_config::WithRococoBulletinMessageBridge,
>(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(Rococo), Parachain(42))))
}
fn prepare_message_delivery_proof(
params: MessageDeliveryProofParams<AccountId>,
) -> bridge_to_bulletin_config::ToRococoBulletinMessagesDeliveryProof {
prepare_message_delivery_proof_from_grandpa_chain::<
Runtime,
bridge_common_config::BridgeGrandpaRococoBulletinInstance,
bridge_to_bulletin_config::WithRococoBulletinMessageBridge,
>(params)
}
fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool {
use cumulus_primitives_core::XcmpMessageSource;
!XcmpQueue::take_outbound_messages(usize::MAX).is_empty()
}
}
use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof;
use pallet_bridge_parachains::benchmarking::Config as BridgeParachainsConfig;
use pallet_bridge_relayers::benchmarking::{
@@ -1134,7 +1232,10 @@ mod tests {
frame_system::CheckWeight::new(),
pallet_transaction_payment::ChargeTransactionPayment::from(10),
BridgeRejectObsoleteHeadersAndMessages,
(bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),)
(
bridge_to_westend_config::OnBridgeHubRococoRefundBridgeHubWestendMessages::default(),
bridge_to_bulletin_config::OnBridgeHubRococoRefundRococoBulletinMessages::default(),
)
);
// for BridgeHubRococo