Skip to content

Commit

Permalink
Parachains finality relay (paritytech#1199)
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatonik authored and serban300 committed Apr 8, 2024
1 parent 57c1cd1 commit 6117d2e
Show file tree
Hide file tree
Showing 26 changed files with 1,814 additions and 67 deletions.
2 changes: 2 additions & 0 deletions bridges/bin/millau/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bp-westend = { path = "../../../primitives/chain-westend", default-features = fa
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false }
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }

# Substrate Dependencies
Expand Down Expand Up @@ -102,6 +103,7 @@ std = [
"pallet-beefy-mmr/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-bridge-parachains/std",
"pallet-grandpa/std",
"pallet-mmr/std",
"pallet-randomness-collective-flip/std",
Expand Down
17 changes: 17 additions & 0 deletions bridges/bin/millau/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall;
pub use pallet_bridge_messages::Call as MessagesCall;
pub use pallet_bridge_parachains::Call as BridgeParachainsCall;
pub use pallet_sudo::Call as SudoCall;
pub use pallet_timestamp::Call as TimestampCall;

Expand Down Expand Up @@ -461,6 +462,19 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
type BridgedChainId = RialtoChainId;
}

parameter_types! {
pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME;
}

/// Instance of the with-Rialto parachains token swap pallet.
pub type WitRialtoParachainsInstance = ();

impl pallet_bridge_parachains::Config<WitRialtoParachainsInstance> for Runtime {
type BridgesGrandpaPalletInstance = RialtoGrandpaInstance;
type ParasPalletName = RialtoParasPalletName;
type HeadsToKeep = HeadersToKeep;
}

construct_runtime!(
pub enum Runtime where
Block = Block,
Expand Down Expand Up @@ -495,6 +509,9 @@ construct_runtime!(
// Westend bridge modules.
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Config<T>, Storage},

// Rialto parachains bridge modules.
BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage},

// Pallet for sending XCM.
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config} = 99,
}
Expand Down
2 changes: 2 additions & 0 deletions bridges/modules/parachains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde = { version = "1.0.101", optional = true }

# Bridge Dependencies

bp-parachains = { path = "../../primitives/parachains", default-features = false }
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
bp-runtime = { path = "../../primitives/runtime", default-features = false }
pallet-bridge-grandpa = { path = "../grandpa", default-features = false }
Expand All @@ -34,6 +35,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
[features]
default = ["std"]
std = [
"bp-parachains/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"codec/std",
Expand Down
41 changes: 21 additions & 20 deletions bridges/modules/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

#![cfg_attr(not(feature = "std"), no_std)]

use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaId, ParachainHeadsProof};
use bp_parachains::parachain_head_storage_key_at_source;
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
use codec::{Decode, Encode};
use frame_support::RuntimeDebug;
use scale_info::TypeInfo;
Expand Down Expand Up @@ -73,12 +74,16 @@ pub mod pallet {
pub trait Config<I: 'static = ()>:
pallet_bridge_grandpa::Config<Self::BridgesGrandpaPalletInstance>
{
/// Instance of bridges GRANDPA pallet that this pallet is linked to.
/// Instance of bridges GRANDPA pallet (within this runtime) that this pallet is linked to.
///
/// The GRANDPA pallet instance must be configured to import headers of relay chain that
/// we're interested in.
type BridgesGrandpaPalletInstance: 'static;

/// Name of the `paras` pallet in the `construct_runtime!()` call at the bridged chain.
#[pallet::constant]
type ParasPalletName: Get<&'static str>;

/// Maximal number of single parachain heads to keep in the storage.
///
/// The setting is there to prevent growing the on-chain state indefinitely. Note
Expand Down Expand Up @@ -129,7 +134,7 @@ pub mod pallet {
_origin: OriginFor<T>,
relay_block_hash: RelayBlockHash,
parachains: Vec<ParaId>,
parachain_heads_proof: ParachainHeadsProof,
parachain_heads_proof: ParaHeadsProof,
) -> DispatchResult {
// we'll need relay chain header to verify that parachains heads are always increasing.
let relay_block = pallet_bridge_grandpa::ImportedHeaders::<
Expand Down Expand Up @@ -190,7 +195,8 @@ pub mod pallet {
storage: &bp_runtime::StorageProofChecker<RelayBlockHasher>,
parachain: ParaId,
) -> Option<ParaHead> {
let parachain_head_key = storage_keys::parachain_head_key(parachain);
let parachain_head_key =
parachain_head_storage_key_at_source(T::ParasPalletName::get(), parachain);
let parachain_head = storage.read_value(parachain_head_key.0.as_ref()).ok()??;
let parachain_head = ParaHead::decode(&mut &parachain_head[..]).ok()?;
Some(parachain_head)
Expand Down Expand Up @@ -257,6 +263,12 @@ pub mod pallet {
updated_head_hash,
);
ImportedParaHeads::<T, I>::insert(parachain, updated_head_hash, updated_head);
log::trace!(
target: "runtime::bridge-parachains",
"Updated head of parachain {:?} to {}",
parachain,
updated_head_hash,
);

// remove old head
if let Ok(head_hash_to_prune) = head_hash_to_prune {
Expand All @@ -274,22 +286,10 @@ pub mod pallet {
}
}

pub mod storage_keys {
use super::*;
use bp_runtime::storage_map_final_key;
use frame_support::Twox64Concat;
use sp_core::storage::StorageKey;

/// Storage key of the parachain head in the runtime storage of relay chain.
pub fn parachain_head_key(parachain: ParaId) -> StorageKey {
storage_map_final_key::<Twox64Concat>("Paras", "Heads", &parachain.encode())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{run_test, test_relay_header, Origin, TestRuntime};
use crate::mock::{run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME};

use bp_test_utils::{authority_list, make_default_justification};
use frame_support::{assert_noop, assert_ok, traits::OnInitialize};
Expand Down Expand Up @@ -330,13 +330,14 @@ mod tests {

fn prepare_parachain_heads_proof(
heads: Vec<(ParaId, ParaHead)>,
) -> (RelayBlockHash, ParachainHeadsProof) {
) -> (RelayBlockHash, ParaHeadsProof) {
let mut root = Default::default();
let mut mdb = MemoryDB::default();
{
let mut trie = TrieDBMutV1::<RelayBlockHasher>::new(&mut mdb, &mut root);
for (parachain, head) in heads {
let storage_key = storage_keys::parachain_head_key(parachain);
let storage_key =
parachain_head_storage_key_at_source(PARAS_PALLET_NAME, parachain);
trie.insert(&storage_key.0, &head.encode())
.map_err(|_| "TrieMut::insert has failed")
.expect("TrieMut::insert should not fail in tests");
Expand Down Expand Up @@ -372,7 +373,7 @@ mod tests {
fn import_parachain_1_head(
relay_chain_block: RelayBlockNumber,
relay_state_root: RelayBlockHash,
proof: ParachainHeadsProof,
proof: ParaHeadsProof,
) -> sp_runtime::DispatchResult {
Pallet::<TestRuntime>::submit_parachain_heads(
Origin::signed(1),
Expand Down
4 changes: 4 additions & 0 deletions bridges/modules/parachains/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub type RelayBlockHeader =
type Block = frame_system::mocking::MockBlock<TestRuntime>;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;

pub const PARAS_PALLET_NAME: &str = "Paras";

construct_runtime! {
pub enum TestRuntime where
Block = Block,
Expand Down Expand Up @@ -103,10 +105,12 @@ impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance2> for TestRun

parameter_types! {
pub const HeadsToKeep: u32 = 4;
pub const ParasPalletName: &'static str = PARAS_PALLET_NAME;
}

impl pallet_bridge_parachains::Config for TestRuntime {
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
type ParasPalletName = ParasPalletName;
type HeadsToKeep = HeadsToKeep;
}

Expand Down
3 changes: 3 additions & 0 deletions bridges/primitives/chain-millau/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages";
/// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime.
pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate";

/// Name of the With-Rialto parachains bridge pallet name in the Millau runtime.
pub const BRIDGE_PARAS_PALLET_NAME: &str = "BridgeRialtoParachains";

/// Name of the `MillauFinalityApi::best_finalized` runtime method.
pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized";

Expand Down
34 changes: 34 additions & 0 deletions bridges/primitives/parachains/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "bp-parachains"
description = "Primitives of parachains module."
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
serde = { version = "1.0", optional = true, features = ["derive"] }

# Bridge dependencies

bp-polkadot-core = { path = "../polkadot-core", default-features = false }
bp-runtime = { path = "../runtime", default-features = false }

# Substrate dependencies

frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

[features]
default = ["std"]
std = [
"bp-polkadot-core/std",
"bp-runtime/std",
"codec/std",
"frame-support/std",
"scale-info/std",
"serde",
"sp-core/std",
]
68 changes: 68 additions & 0 deletions bridges/primitives/parachains/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.

// Parity Bridges Common 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.

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

//! Primitives of parachains module.

#![cfg_attr(not(feature = "std"), no_std)]

use bp_polkadot_core::{
parachains::{ParaHash, ParaId},
BlockNumber as RelayBlockNumber,
};
use codec::{Decode, Encode};
use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat};
use scale_info::TypeInfo;
use sp_core::storage::StorageKey;

/// Best known parachain head hash.
#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)]
pub struct BestParaHeadHash {
/// Number of relay block where this head has been read.
///
/// Parachain head is opaque to relay chain. So we can't simply decode it as a header of
/// parachains and call `block_number()` on it. Instead, we're using the fact that parachain
/// head is always built on top of previous head (because it is blockchain) and relay chain
/// always imports parachain heads in order. What it means for us is that at any given
/// **finalized** relay block `B`, head of parachain will be ancestor (or the same) of all
/// parachain heads available at descendants of `B`.
pub at_relay_block_number: RelayBlockNumber,
/// Hash of parachain head.
pub head_hash: ParaHash,
}

/// Returns runtime storage key of given parachain head at the source chain.
///
/// The head is stored by the `paras` pallet in the `Heads` map.
pub fn parachain_head_storage_key_at_source(
paras_pallet_name: &str,
para_id: ParaId,
) -> StorageKey {
bp_runtime::storage_map_final_key::<Twox64Concat>(paras_pallet_name, "Heads", &para_id.encode())
}

/// Returns runtime storage key of best known parachain head at the target chain.
///
/// The head is stored by the `pallet-bridge-parachains` pallet in the `BestParaHeads` map.
pub fn parachain_head_storage_key_at_target(
bridge_parachains_pallet_name: &str,
para_id: ParaId,
) -> StorageKey {
bp_runtime::storage_map_final_key::<Blake2_128Concat>(
bridge_parachains_pallet_name,
"BestParaHeads",
&para_id.encode(),
)
}
2 changes: 1 addition & 1 deletion bridges/primitives/polkadot-core/src/parachains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ impl ParaHead {
pub type ParaHash = crate::Hash;

/// Raw storage proof of parachain heads, stored in polkadot-like chain runtime.
pub type ParachainHeadsProof = Vec<Vec<u8>>;
pub type ParaHeadsProof = Vec<Vec<u8>>;
2 changes: 2 additions & 0 deletions bridges/relays/bin-substrate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ bp-kusama = { path = "../../primitives/chain-kusama" }
bp-messages = { path = "../../primitives/messages" }
bp-millau = { path = "../../primitives/chain-millau" }
bp-polkadot = { path = "../../primitives/chain-polkadot" }
bp-polkadot-core = { path = "../../primitives/polkadot-core" }
bp-rialto = { path = "../../primitives/chain-rialto" }
bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" }
bp-rococo = { path = "../../primitives/chain-rococo" }
Expand All @@ -39,6 +40,7 @@ messages-relay = { path = "../messages" }
millau-runtime = { path = "../../bin/millau/runtime" }
pallet-bridge-grandpa = { path = "../../modules/grandpa" }
pallet-bridge-messages = { path = "../../modules/messages" }
parachains-relay = { path = "../parachains" }
relay-kusama-client = { path = "../client-kusama" }
relay-millau-client = { path = "../client-millau" }
relay-polkadot-client = { path = "../client-polkadot" }
Expand Down
1 change: 1 addition & 0 deletions bridges/relays/bin-substrate/src/chains/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod polkadot_headers_to_kusama;
pub mod polkadot_messages_to_kusama;
pub mod rialto_headers_to_millau;
pub mod rialto_messages_to_millau;
pub mod rialto_parachains_to_millau;
pub mod rococo_headers_to_wococo;
pub mod rococo_messages_to_wococo;
pub mod westend_headers_to_millau;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.

// Parity Bridges Common 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.

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

//! Rialto-to-Millau parachains sync entrypoint.

use parachains_relay::ParachainsPipeline;
use relay_millau_client::Millau;
use relay_rialto_client::Rialto;
use substrate_relay_helper::parachains_target::DirectSubmitParachainHeadsCallBuilder;

/// Rialto-to-Millau parachains sync description.
#[derive(Clone, Debug)]
pub struct RialtoToMillauParachains;

impl ParachainsPipeline for RialtoToMillauParachains {
type SourceChain = Rialto;
type TargetChain = Millau;
}

/// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline.
pub type RialtoToMillauParachainsSubmitParachainHeadsCallBuilder =
DirectSubmitParachainHeadsCallBuilder<
RialtoToMillauParachains,
millau_runtime::Runtime,
millau_runtime::WitRialtoParachainsInstance,
>;
Loading

0 comments on commit 6117d2e

Please sign in to comment.