Skip to content

Commit

Permalink
Add Wococo<>Rococo Header Relayer (paritytech#925)
Browse files Browse the repository at this point in the history
* Add Wococo primitives crate

* Add more Wococo boilerplate code

* Add CLI support for initializing the Wococo<>Rococo bridge

* Add support for relaying headers between Rococo and Wococo

* Fix test

* RustFmt

* Fix compilation issues related to enum naming

* Bump Rococo `spec_version`

* Remove stray Westend references
  • Loading branch information
HCastano authored and serban300 committed Apr 10, 2024
1 parent 5c960d0 commit aece6d7
Show file tree
Hide file tree
Showing 14 changed files with 602 additions and 8 deletions.
10 changes: 5 additions & 5 deletions bridges/primitives/chain-rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: sp_version::create_runtime_str!("rococo"),
impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"),
authoring_version: 0,
spec_version: 231,
spec_version: 232,
impl_version: 0,
apis: sp_version::create_apis_vec![[]],
transaction_version: 0,
Expand All @@ -55,14 +55,14 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)]
pub enum Call {
/// Generic bridge pallet.
#[codec(index = 40)]
BridgeCall(BridgeGrandpaCall),
/// Wococo bridge pallet.
#[codec(index = 41)]
BridgeGrandpaWococo(BridgeGrandpaWococoCall),
}

#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)]
#[allow(non_camel_case_types)]
pub enum BridgeGrandpaCall {
pub enum BridgeGrandpaWococoCall {
#[codec(index = 0)]
submit_finality_proof(
<PolkadotLike as Chain>::Header,
Expand Down
36 changes: 36 additions & 0 deletions bridges/primitives/chain-wococo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "bp-wococo"
description = "Primitives of Wococo runtime."
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] }

# Bridge Dependencies
bp-header-chain = { path = "../header-chain", default-features = false }
bp-messages = { path = "../messages", default-features = false }
bp-polkadot-core = { path = "../polkadot-core", default-features = false }
bp-runtime = { path = "../runtime", default-features = false }

# Substrate Based Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

[features]
default = ["std"]
std = [
"bp-header-chain/std",
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"parity-scale-codec/std",
"sp-api/std",
"sp-runtime/std",
"sp-std/std",
"sp-version/std",
]
172 changes: 172 additions & 0 deletions bridges/primitives/chain-wococo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// 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/>.

#![cfg_attr(not(feature = "std"), no_std)]
// RuntimeApi generated functions
#![allow(clippy::too_many_arguments)]
// Runtime-generated DecodeLimit::decode_all_with_depth_limit
#![allow(clippy::unnecessary_mut_passed)]

use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight};
use bp_runtime::Chain;
use sp_std::prelude::*;
use sp_version::RuntimeVersion;

pub use bp_polkadot_core::*;

/// Wococo Chain
pub type Wococo = PolkadotLike;

pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic<Call>;

// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: sp_version::create_runtime_str!("rococo"),
impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"),
authoring_version: 0,
spec_version: 232,
impl_version: 0,
apis: sp_version::create_apis_vec![[]],
transaction_version: 0,
};

/// Wococo Runtime `Call` enum.
///
/// The enum represents a subset of possible `Call`s we can send to Rococo chain.
/// Ideally this code would be auto-generated from Metadata, because we want to
/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s.
///
/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo
/// `construct_runtime`, so that we maintain SCALE-compatibility.
///
/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs
#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)]
pub enum Call {
/// Rococo bridge pallet.
#[codec(index = 40)]
BridgeGrandpaRococo(BridgeGrandpaRococoCall),
}

#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)]
#[allow(non_camel_case_types)]
pub enum BridgeGrandpaRococoCall {
#[codec(index = 0)]
submit_finality_proof(
<PolkadotLike as Chain>::Header,
bp_header_chain::justification::GrandpaJustification<<PolkadotLike as Chain>::Header>,
),
#[codec(index = 1)]
initialize(bp_header_chain::InitializationData<<PolkadotLike as Chain>::Header>),
}

impl sp_runtime::traits::Dispatchable for Call {
type Origin = ();
type Config = ();
type Info = ();
type PostInfo = ();

fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
unimplemented!("The Call is not expected to be dispatched.")
}
}

// We use this to get the account on Wococo (target) which is derived from Rococo's (source)
// account.
pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount<AccountId>) -> AccountId {
let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_BRIDGE_INSTANCE, id);
AccountIdConverter::convert(encoded_id)
}

/// Name of the `WococoFinalityApi::best_finalized` runtime method.
pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized";
/// Name of the `WococoFinalityApi::is_known_header` runtime method.
pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_header";

/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method.
pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str =
"ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee";
/// Name of the `ToWococoOutboundLaneApi::messages_dispatch_weight` runtime method.
pub const TO_WOCOCO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToWococoOutboundLaneApi_messages_dispatch_weight";
/// Name of the `ToWococoOutboundLaneApi::latest_generated_nonce` runtime method.
pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_generated_nonce";
/// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method.
pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_received_nonce";

/// Name of the `FromWococoInboundLaneApi::latest_received_nonce` runtime method.
pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_received_nonce";
/// Name of the `FromWococoInboundLaneApi::latest_onfirmed_nonce` runtime method.
pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_confirmed_nonce";
/// Name of the `FromWococoInboundLaneApi::unrewarded_relayers_state` runtime method.
pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromWococoInboundLaneApi_unrewarded_relayers_state";

sp_api::decl_runtime_apis! {
/// API for querying information about the finalized Wococo headers.
///
/// This API is implemented by runtimes that are bridging with the Wococo chain, not the
/// Wococo runtime itself.
pub trait WococoFinalityApi {
/// Returns number and hash of the best finalized header known to the bridge module.
fn best_finalized() -> (BlockNumber, Hash);
/// Returns true if the header is known to the runtime.
fn is_known_header(hash: Hash) -> bool;
}

/// Outbound message lane API for messages that are sent to Wococo chain.
///
/// This API is implemented by runtimes that are sending messages to Wococo chain, not the
/// Wococo runtime itself.
pub trait ToWococoOutboundLaneApi<OutboundMessageFee: Parameter, OutboundPayload: Parameter> {
/// Estimate message delivery and dispatch fee that needs to be paid by the sender on
/// this chain.
///
/// Returns `None` if message is too expensive to be sent to Wococo from this chain.
///
/// Please keep in mind that this method returns lowest message fee required for message
/// to be accepted to the lane. It may be good idea to pay a bit over this price to account
/// future exchange rate changes and guarantee that relayer would deliver your message
/// to the target chain.
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
) -> Option<OutboundMessageFee>;
/// Returns total dispatch weight and encoded payload size of all messages in given inclusive range.
///
/// If some (or all) messages are missing from the storage, they'll also will
/// be missing from the resulting vector. The vector is ordered by the nonce.
fn messages_dispatch_weight(
lane: LaneId,
begin: MessageNonce,
end: MessageNonce,
) -> Vec<(MessageNonce, Weight, u32)>;
/// Returns nonce of the latest message, received by bridged chain.
fn latest_received_nonce(lane: LaneId) -> MessageNonce;
/// Returns nonce of the latest message, generated by given lane.
fn latest_generated_nonce(lane: LaneId) -> MessageNonce;
}

/// Inbound message lane API for messages sent by Wococo chain.
///
/// This API is implemented by runtimes that are receiving messages from Wococo chain, not the
/// Wococo runtime itself.
pub trait FromWococoInboundLaneApi {
/// Returns nonce of the latest message, received by given lane.
fn latest_received_nonce(lane: LaneId) -> MessageNonce;
/// Nonce of latest message that has been confirmed to the bridged chain.
fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce;
/// State of the unrewarded relayers set at given lane.
fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState;
}
}
4 changes: 2 additions & 2 deletions bridges/primitives/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ pub const KUSAMA_BRIDGE_INSTANCE: InstanceId = *b"ksma";
/// Bridge-with-Rococo instance id.
pub const ROCOCO_BRIDGE_INSTANCE: InstanceId = *b"roco";

/// Bridge-with-Westend instance id.
pub const WESTEND_BRIDGE_INSTANCE: InstanceId = *b"wend";
/// Bridge-with-Wococo instance id.
pub const WOCOCO_BRIDGE_INSTANCE: InstanceId = *b"woco";

/// Call-dispatch module prefix.
pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch";
Expand Down
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-millau = { path = "../../primitives/chain-millau" }
bp-polkadot = { path = "../../primitives/chain-polkadot" }
bp-rialto = { path = "../../primitives/chain-rialto" }
bp-rococo = { path = "../../primitives/chain-rococo" }
bp-wococo = { path = "../../primitives/chain-wococo" }
bp-runtime = { path = "../../primitives/runtime" }
bp-westend = { path = "../../primitives/chain-westend" }
bridge-runtime-common = { path = "../../bin/runtime-common" }
Expand All @@ -42,6 +43,7 @@ relay-millau-client = { path = "../client-millau" }
relay-polkadot-client = { path = "../client-polkadot" }
relay-rialto-client = { path = "../client-rialto" }
relay-rococo-client = { path = "../client-rococo" }
relay-wococo-client = { path = "../client-wococo" }
relay-substrate-client = { path = "../client-substrate" }
relay-utils = { path = "../utils" }
relay-westend-client = { path = "../client-westend" }
Expand Down
5 changes: 4 additions & 1 deletion bridges/relays/bin-substrate/src/chains/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ pub mod millau_headers_to_rialto;
pub mod millau_messages_to_rialto;
pub mod rialto_headers_to_millau;
pub mod rialto_messages_to_millau;
pub mod rococo_headers_to_wococo;
pub mod westend_headers_to_millau;
pub mod wococo_headers_to_rococo;

mod millau;
mod rialto;
mod rococo;
mod westend;
mod wococo;

use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams};

Expand Down Expand Up @@ -268,7 +271,7 @@ mod rococo_tests {
votes_ancestries: vec![],
};

let actual = bp_rococo::BridgeGrandpaCall::submit_finality_proof(header.clone(), justification.clone());
let actual = bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(header.clone(), justification.clone());
let expected = millau_runtime::BridgeGrandpaRialtoCall::<millau_runtime::Runtime>::submit_finality_proof(
header,
justification,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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/>.

//! Rococo-to-Wococo headers sync entrypoint.

use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};

use bp_header_chain::justification::GrandpaJustification;
use codec::Encode;
use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader};
use relay_substrate_client::{Chain, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair};

/// Rococo-to-Wococo finality sync pipeline.
pub(crate) type RococoFinalityToWococo = SubstrateFinalityToSubstrate<Rococo, Wococo, WococoSigningParams>;

impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;

type TargetChain = Wococo;

fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
crate::chains::add_polkadot_kusama_price_metrics::<Self>(params)
}

fn transactions_author(&self) -> bp_wococo::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}

fn make_submit_finality_proof_transaction(
&self,
transaction_nonce: <Wococo as Chain>::Index,
header: RococoSyncHeader,
proof: GrandpaJustification<bp_rococo::Header>,
) -> Bytes {
let call = bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::submit_finality_proof(
header.into_inner(),
proof,
));
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);

Bytes(transaction.encode())
}
}
Loading

0 comments on commit aece6d7

Please sign in to comment.