Parachains finality relay (#1199)

This commit is contained in:
Svyatoslav Nikolsky
2022-05-20 11:34:52 +03:00
committed by Bastian Köcher
parent f64357e7e8
commit 03c2f06a27
26 changed files with 1814 additions and 67 deletions
+2
View File
@@ -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" }
@@ -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" }
@@ -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;
@@ -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,
>;
@@ -36,6 +36,7 @@ mod reinit_bridge;
mod relay_headers;
mod relay_headers_and_messages;
mod relay_messages;
mod relay_parachains;
mod resubmit_transactions;
/// Parse relay CLI args.
@@ -85,6 +86,8 @@ pub enum Command {
ResubmitTransactions(resubmit_transactions::ResubmitTransactions),
/// Register parachain.
RegisterParachain(register_parachain::RegisterParachain),
///
RelayParachains(relay_parachains::RelayParachains),
}
impl Command {
@@ -118,6 +121,7 @@ impl Command {
Self::EstimateFee(arg) => arg.run().await?,
Self::ResubmitTransactions(arg) => arg.run().await?,
Self::RegisterParachain(arg) => arg.run().await?,
Self::RelayParachains(arg) => arg.run().await?,
}
Ok(())
}
@@ -0,0 +1,119 @@
// 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/>.
use bp_polkadot_core::parachains::ParaId;
use parachains_relay::{parachains_loop::ParachainSyncParams, ParachainsPipeline};
use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames};
use substrate_relay_helper::{
parachains_source::ParachainsSource, parachains_target::ParachainsTarget, TransactionParams,
};
use crate::cli::{
PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams,
};
/// Start parachain heads relayer process.
#[derive(StructOpt)]
pub struct RelayParachains {
/// A bridge instance to relay parachains heads for.
#[structopt(possible_values = RelayParachainsBridge::VARIANTS, case_insensitive = true)]
bridge: RelayParachainsBridge,
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
target: TargetConnectionParams,
#[structopt(flatten)]
target_sign: TargetSigningParams,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
}
/// Parachain heads relay bridge.
#[derive(Debug, EnumString, EnumVariantNames)]
#[strum(serialize_all = "kebab_case")]
pub enum RelayParachainsBridge {
RialtoToMillau,
}
macro_rules! select_bridge {
($bridge: expr, $generic: tt) => {
match $bridge {
RelayParachainsBridge::RialtoToMillau => {
use crate::chains::rialto_parachains_to_millau::{
RialtoToMillauParachains as Pipeline,
RialtoToMillauParachainsSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder,
};
use bp_millau::BRIDGE_PARAS_PALLET_NAME as BRIDGE_PARAS_PALLET_NAME_AT_TARGET;
use bp_rialto::PARAS_PALLET_NAME as PARAS_PALLET_NAME_AT_SOURCE;
use relay_millau_client::Millau as TargetTransactionSignScheme;
$generic
},
}
};
}
impl RelayParachains {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
select_bridge!(self.bridge, {
type SourceChain = <Pipeline as ParachainsPipeline>::SourceChain;
type TargetChain = <Pipeline as ParachainsPipeline>::TargetChain;
let source_client = self.source.to_client::<SourceChain>().await?;
let source_client = ParachainsSource::<Pipeline>::new(
source_client,
PARAS_PALLET_NAME_AT_SOURCE.into(),
);
let taret_transaction_params = TransactionParams {
signer: self.target_sign.to_keypair::<TargetChain>()?,
mortality: self.target_sign.target_transactions_mortality,
};
let target_client = self.target.to_client::<TargetChain>().await?;
let target_client = ParachainsTarget::<
Pipeline,
TargetTransactionSignScheme,
SubmitParachainHeadsCallBuilder,
>::new(
target_client.clone(),
taret_transaction_params,
BRIDGE_PARAS_PALLET_NAME_AT_TARGET.into(),
);
let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into();
GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?;
parachains_relay::parachains_loop::run(
source_client,
target_client,
ParachainSyncParams {
parachains: vec![ParaId(2000)],
stall_timeout: std::time::Duration::from_secs(60),
strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any,
},
metrics_params,
futures::future::pending(),
)
.await
.map_err(|e| anyhow::format_err!("{}", e))
})
}
}
+4 -2
View File
@@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
async-std = { version = "1.6.5", features = ["attributes"] }
async-trait = "0.1"
codec = { package = "parity-scale-codec", version = "3.0.0" }
futures = "0.3.7"
jsonrpsee = { version = "0.8", features = ["macros", "ws-client"] }
log = "0.4.11"
num-traits = "0.2"
@@ -44,5 +45,6 @@ sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
#[dev-dependencies]
futures = "0.3.7"
[features]
default = []
test-helpers = []
+1 -44
View File
@@ -196,7 +196,7 @@ impl<C: ChainWithBalances> Environment<C> for Client<C> {
#[cfg(test)]
mod tests {
use super::*;
use frame_support::weights::{IdentityFee, Weight};
use crate::test_chain::TestChain;
use futures::{
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
future::FutureExt,
@@ -204,49 +204,6 @@ mod tests {
SinkExt,
};
#[derive(Debug, Clone)]
struct TestChain;
impl bp_runtime::Chain for TestChain {
type BlockNumber = u32;
type Hash = sp_core::H256;
type Hasher = sp_runtime::traits::BlakeTwo256;
type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
type AccountId = u32;
type Balance = u32;
type Index = u32;
type Signature = sp_runtime::testing::TestSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
}
impl Chain for TestChain {
const NAME: &'static str = "Test";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader";
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
const STORAGE_PROOF_OVERHEAD: u32 = 0;
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0;
type SignedBlock = sp_runtime::generic::SignedBlock<
sp_runtime::generic::Block<Self::Header, sp_runtime::OpaqueExtrinsic>,
>;
type Call = ();
type WeightToFee = IdentityFee<u32>;
}
impl ChainWithBalances for TestChain {
fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey {
unreachable!()
}
}
struct TestEnvironment {
runtime_version_rx: UnboundedReceiver<RuntimeVersion>,
free_native_balance_rx: UnboundedReceiver<u32>,
@@ -26,6 +26,7 @@ mod sync_header;
pub mod guard;
pub mod metrics;
pub mod test_chain;
use std::time::Duration;
@@ -0,0 +1,71 @@
// 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/>.
//! Pallet provides a set of guard functions that are running in background threads
//! and are aborting process if some condition fails.
//! Test chain implementation to use in tests.
#![cfg(any(feature = "test-helpers", test))]
use crate::{Chain, ChainWithBalances};
use frame_support::weights::{IdentityFee, Weight};
use std::time::Duration;
/// Chain that may be used in tests.
#[derive(Clone, Debug, PartialEq)]
pub struct TestChain;
impl bp_runtime::Chain for TestChain {
type BlockNumber = u32;
type Hash = sp_core::H256;
type Hasher = sp_runtime::traits::BlakeTwo256;
type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
type AccountId = u32;
type Balance = u32;
type Index = u32;
type Signature = sp_runtime::testing::TestSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
}
impl Chain for TestChain {
const NAME: &'static str = "Test";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod";
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0);
const STORAGE_PROOF_OVERHEAD: u32 = 0;
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0;
type SignedBlock = sp_runtime::generic::SignedBlock<
sp_runtime::generic::Block<Self::Header, sp_runtime::OpaqueExtrinsic>,
>;
type Call = ();
type WeightToFee = IdentityFee<u32>;
}
impl ChainWithBalances for TestChain {
fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey {
unreachable!()
}
}
@@ -18,16 +18,20 @@ log = "0.4.14"
# Bridge dependencies
bp-header-chain = { path = "../../primitives/header-chain" }
bp-parachains = { path = "../../primitives/parachains" }
bp-polkadot-core = { path = "../../primitives/polkadot-core" }
bridge-runtime-common = { path = "../../bin/runtime-common" }
finality-grandpa = { version = "0.15.0" }
finality-relay = { path = "../finality" }
parachains-relay = { path = "../parachains" }
relay-utils = { path = "../utils" }
messages-relay = { path = "../messages" }
relay-substrate-client = { path = "../client-substrate" }
pallet-bridge-grandpa = { path = "../../modules/grandpa" }
pallet-bridge-messages = { path = "../../modules/messages" }
pallet-bridge-parachains = { path = "../../modules/parachains" }
bp-runtime = { path = "../../primitives/runtime" }
bp-messages = { path = "../../primitives/messages" }
@@ -29,6 +29,8 @@ pub mod messages_metrics;
pub mod messages_source;
pub mod messages_target;
pub mod on_demand_headers;
pub mod parachains_source;
pub mod parachains_target;
/// Default relay loop stall timeout. If transactions generated by relay are immortal, then
/// this timeout is used.
@@ -0,0 +1,91 @@
// 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/>.
//! Parachain heads source.
use async_trait::async_trait;
use bp_parachains::parachain_head_storage_key_at_source;
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
use codec::Decode;
use parachains_relay::{parachains_loop::SourceClient, ParachainsPipeline};
use relay_substrate_client::{Client, Error as SubstrateError, HeaderIdOf};
use relay_utils::relay_loop::Client as RelayClient;
/// Substrate client as parachain heads source.
#[derive(Clone)]
pub struct ParachainsSource<P: ParachainsPipeline> {
client: Client<P::SourceChain>,
paras_pallet_name: String,
}
impl<P: ParachainsPipeline> ParachainsSource<P> {
/// Creates new parachains source client.
pub fn new(client: Client<P::SourceChain>, paras_pallet_name: String) -> Self {
ParachainsSource { client, paras_pallet_name }
}
}
#[async_trait]
impl<P: ParachainsPipeline> RelayClient for ParachainsSource<P> {
type Error = SubstrateError;
async fn reconnect(&mut self) -> Result<(), SubstrateError> {
self.client.reconnect().await
}
}
#[async_trait]
impl<P: ParachainsPipeline> SourceClient<P> for ParachainsSource<P> {
async fn ensure_synced(&self) -> Result<bool, Self::Error> {
match self.client.ensure_synced().await {
Ok(_) => Ok(true),
Err(SubstrateError::ClientNotSynced(_)) => Ok(false),
Err(e) => Err(e),
}
}
async fn parachain_head(
&self,
at_block: HeaderIdOf<P::SourceChain>,
para_id: ParaId,
) -> Result<Option<ParaHash>, Self::Error> {
let storage_key = parachain_head_storage_key_at_source(&self.paras_pallet_name, para_id);
let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?;
let para_head = para_head.map(|h| ParaHead::decode(&mut &h.0[..])).transpose()?;
let para_hash = para_head.map(|h| h.hash());
Ok(para_hash)
}
async fn prove_parachain_heads(
&self,
at_block: HeaderIdOf<P::SourceChain>,
parachains: &[ParaId],
) -> Result<ParaHeadsProof, Self::Error> {
let storage_keys = parachains
.iter()
.map(|para_id| parachain_head_storage_key_at_source(&self.paras_pallet_name, *para_id))
.collect();
let parachain_heads_proof = self
.client
.prove_storage(storage_keys, at_block.1)
.await?
.iter_nodes()
.collect();
Ok(parachain_heads_proof)
}
}
@@ -0,0 +1,211 @@
// 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/>.
//! Parachain heads target.
use crate::TransactionParams;
use async_trait::async_trait;
use bp_parachains::{parachain_head_storage_key_at_target, BestParaHeadHash};
use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId};
use codec::{Decode, Encode};
use pallet_bridge_parachains::{
Call as BridgeParachainsCall, Config as BridgeParachainsConfig, RelayBlockHash,
RelayBlockHasher, RelayBlockNumber,
};
use parachains_relay::{parachains_loop::TargetClient, ParachainsPipeline};
use relay_substrate_client::{
AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError,
HashOf, HeaderIdOf, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction,
};
use relay_utils::{relay_loop::Client as RelayClient, HeaderId};
use sp_core::{Bytes, Pair};
use sp_runtime::traits::Header as HeaderT;
use std::marker::PhantomData;
/// Different ways of building `submit_parachain_heads` calls.
pub trait SubmitParachainHeadsCallBuilder<P: ParachainsPipeline>: 'static + Send + Sync {
/// Given parachains and their heads proof, build call of `submit_parachain_heads`
/// function of bridge parachains module at the target chain.
fn build_submit_parachain_heads_call(
relay_block_hash: HashOf<P::SourceChain>,
parachains: Vec<ParaId>,
parachain_heads_proof: ParaHeadsProof,
) -> CallOf<P::TargetChain>;
}
/// Building `submit_parachain_heads` call when you have direct access to the target
/// chain runtime.
pub struct DirectSubmitParachainHeadsCallBuilder<P, R, I> {
_phantom: PhantomData<(P, R, I)>,
}
impl<P, R, I> SubmitParachainHeadsCallBuilder<P> for DirectSubmitParachainHeadsCallBuilder<P, R, I>
where
P: ParachainsPipeline,
P::SourceChain: Chain<Hash = RelayBlockHash>,
R: BridgeParachainsConfig<I> + Send + Sync,
I: 'static + Send + Sync,
R::BridgedChain: bp_runtime::Chain<
BlockNumber = RelayBlockNumber,
Hash = RelayBlockHash,
Hasher = RelayBlockHasher,
>,
CallOf<P::TargetChain>: From<BridgeParachainsCall<R, I>>,
{
fn build_submit_parachain_heads_call(
relay_block_hash: HashOf<P::SourceChain>,
parachains: Vec<ParaId>,
parachain_heads_proof: ParaHeadsProof,
) -> CallOf<P::TargetChain> {
BridgeParachainsCall::<R, I>::submit_parachain_heads {
relay_block_hash,
parachains,
parachain_heads_proof,
}
.into()
}
}
/// Substrate client as parachain heads source.
pub struct ParachainsTarget<P: ParachainsPipeline, S: TransactionSignScheme, CB> {
client: Client<P::TargetChain>,
transaction_params: TransactionParams<AccountKeyPairOf<S>>,
bridge_paras_pallet_name: String,
_phantom: PhantomData<CB>,
}
impl<P: ParachainsPipeline, S: TransactionSignScheme, CB> ParachainsTarget<P, S, CB> {
/// Creates new parachains target client.
pub fn new(
client: Client<P::TargetChain>,
transaction_params: TransactionParams<AccountKeyPairOf<S>>,
bridge_paras_pallet_name: String,
) -> Self {
ParachainsTarget {
client,
transaction_params,
bridge_paras_pallet_name,
_phantom: Default::default(),
}
}
}
impl<P: ParachainsPipeline, S: TransactionSignScheme, CB> Clone for ParachainsTarget<P, S, CB> {
fn clone(&self) -> Self {
ParachainsTarget {
client: self.client.clone(),
transaction_params: self.transaction_params.clone(),
bridge_paras_pallet_name: self.bridge_paras_pallet_name.clone(),
_phantom: Default::default(),
}
}
}
#[async_trait]
impl<
P: ParachainsPipeline,
S: 'static + TransactionSignScheme,
CB: SubmitParachainHeadsCallBuilder<P>,
> RelayClient for ParachainsTarget<P, S, CB>
{
type Error = SubstrateError;
async fn reconnect(&mut self) -> Result<(), SubstrateError> {
self.client.reconnect().await
}
}
#[async_trait]
impl<P, S, CB> TargetClient<P> for ParachainsTarget<P, S, CB>
where
P: ParachainsPipeline,
S: 'static + TransactionSignScheme<Chain = P::TargetChain>,
CB: SubmitParachainHeadsCallBuilder<P>,
AccountIdOf<P::TargetChain>: From<<AccountKeyPairOf<S> as Pair>::Public>,
{
async fn best_block(&self) -> Result<HeaderIdOf<P::TargetChain>, Self::Error> {
let best_header = self.client.best_header().await?;
let best_hash = best_header.hash();
let best_id = HeaderId(*best_header.number(), best_hash);
Ok(best_id)
}
async fn best_finalized_source_block(
&self,
at_block: &HeaderIdOf<P::TargetChain>,
) -> Result<HeaderIdOf<P::SourceChain>, Self::Error> {
let encoded_best_finalized_source_block = self
.client
.state_call(
P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD.into(),
Bytes(Vec::new()),
Some(at_block.1),
)
.await?;
let decoded_best_finalized_source_block: (
BlockNumberOf<P::SourceChain>,
HashOf<P::SourceChain>,
) = Decode::decode(&mut &encoded_best_finalized_source_block.0[..])
.map_err(SubstrateError::ResponseParseFailed)?;
Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1))
}
async fn parachain_head(
&self,
at_block: HeaderIdOf<P::TargetChain>,
para_id: ParaId,
) -> Result<Option<BestParaHeadHash>, Self::Error> {
let storage_key =
parachain_head_storage_key_at_target(&self.bridge_paras_pallet_name, para_id);
let para_head = self.client.storage_value(storage_key, Some(at_block.1)).await?;
Ok(para_head)
}
async fn submit_parachain_heads_proof(
&self,
at_relay_block: HeaderIdOf<P::SourceChain>,
updated_parachains: Vec<ParaId>,
proof: ParaHeadsProof,
) -> Result<(), Self::Error> {
let genesis_hash = *self.client.genesis_hash();
let transaction_params = self.transaction_params.clone();
let (spec_version, transaction_version) = self.client.simple_runtime_version().await?;
let call =
CB::build_submit_parachain_heads_call(at_relay_block.1, updated_parachains, proof);
self.client
.submit_signed_extrinsic(
self.transaction_params.signer.public().into(),
move |best_block_id, transaction_nonce| {
Ok(Bytes(
S::sign_transaction(SignParam {
spec_version,
transaction_version,
genesis_hash,
signer: transaction_params.signer,
era: TransactionEra::new(best_block_id, transaction_params.mortality),
unsigned: UnsignedTransaction::new(call.into(), transaction_nonce),
})?
.encode(),
))
},
)
.await
.map(drop)
}
}
+28
View File
@@ -0,0 +1,28 @@
[package]
name = "parachains-relay"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
async-std = "1.6.5"
async-trait = "0.1.40"
backoff = "0.2"
futures = "0.3.5"
linked-hash-map = "0.5.3"
log = "0.4.11"
num-traits = "0.2"
parking_lot = "0.11.0"
relay-utils = { path = "../utils" }
# Bridge dependencies
bp-parachains = { path = "../../primitives/parachains" }
bp-polkadot-core = { path = "../../primitives/polkadot-core" }
relay-substrate-client = { path = "../client-substrate" }
[dev-dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0" }
relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
+30
View File
@@ -0,0 +1,30 @@
// 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/>.
use std::fmt::Debug;
use relay_substrate_client::Chain;
pub mod parachains_loop;
pub mod parachains_loop_metrics;
/// Finality proofs synchronization pipeline.
pub trait ParachainsPipeline: 'static + Clone + Debug + Send + Sync {
/// Relay chain which is storing parachain heads in its `paras` module.
type SourceChain: Chain;
/// Target chain (either relay or para) which wants to know about new parachain heads.
type TargetChain: Chain;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,34 @@
// 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/>.
use relay_utils::metrics::{Metric, PrometheusError, Registry};
/// Parachains sync metrics.
#[derive(Clone)]
pub struct ParachainsLoopMetrics;
impl ParachainsLoopMetrics {
/// Create and register parachains loop metrics.
pub fn new(_prefix: Option<&str>) -> Result<Self, PrometheusError> {
Ok(ParachainsLoopMetrics)
}
}
impl Metric for ParachainsLoopMetrics {
fn register(&self, _registry: &Registry) -> Result<(), PrometheusError> {
Ok(())
}
}