Rococo <> Wococo messages relay (#1030)

* MessagesInstance -> BridgedMessagesInstance

* Chain::ID -> Bridge::THIS_CHAIN_ID+Bridge::BRIDGED_CHAIN_ID

* FromBridgedChainEncodedMessageCall<B> -> FromBridgedChainEncodedMessageCall<DecodedCall>

* impl Parameter for ()

* copypaste storage_map_final_key to avoid different runtime references/dummy runtimes

* moved dummy runtime from primitives to relay client

* Rococo <> Wococo messages relays

* send R<>W messages using relay

* fmt

* return Result from get_dispatch_info

* fix benchmarks compilation

* clippy
This commit is contained in:
Svyatoslav Nikolsky
2021-06-25 11:06:14 +03:00
committed by Bastian Köcher
parent c8aeb11b26
commit 165730a2c2
34 changed files with 1090 additions and 242 deletions
@@ -23,7 +23,7 @@ use crate::cli::{
};
use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Decode;
use frame_support::weights::{GetDispatchInfo, Weight};
use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight};
use relay_millau_client::Millau;
use sp_version::RuntimeVersion;
@@ -62,6 +62,10 @@ impl CliEncodeCall for Millau {
},
})
}
fn get_dispatch_info(call: &millau_runtime::Call) -> anyhow::Result<DispatchInfo> {
Ok(call.get_dispatch_info())
}
}
impl CliChain for Millau {
@@ -126,20 +126,12 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
}
/// Millau node as messages source.
type MillauSourceClient = SubstrateMessagesSource<
Millau,
MillauMessagesToRialto,
millau_runtime::Runtime,
millau_runtime::WithRialtoMessagesInstance,
>;
type MillauSourceClient =
SubstrateMessagesSource<Millau, MillauMessagesToRialto, millau_runtime::WithRialtoMessagesInstance>;
/// Rialto node as messages target.
type RialtoTargetClient = SubstrateMessagesTarget<
Rialto,
MillauMessagesToRialto,
rialto_runtime::Runtime,
rialto_runtime::WithMillauMessagesInstance,
>;
type RialtoTargetClient =
SubstrateMessagesTarget<Rialto, MillauMessagesToRialto, rialto_runtime::WithMillauMessagesInstance>;
/// Run Millau-to-Rialto messages sync.
pub async fn run(
@@ -21,8 +21,10 @@ 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 rococo_messages_to_wococo;
pub mod westend_headers_to_millau;
pub mod wococo_headers_to_rococo;
pub mod wococo_messages_to_rococo;
mod millau;
mod rialto;
@@ -271,7 +273,10 @@ mod rococo_tests {
votes_ancestries: vec![],
};
let actual = bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(header.clone(), justification.clone());
let actual = relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(
header.clone(),
justification.clone(),
);
let expected = millau_runtime::BridgeGrandpaRialtoCall::<millau_runtime::Runtime>::submit_finality_proof(
header,
justification,
@@ -23,7 +23,7 @@ use crate::cli::{
};
use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Decode;
use frame_support::weights::{GetDispatchInfo, Weight};
use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight};
use relay_rialto_client::Rialto;
use sp_version::RuntimeVersion;
@@ -60,6 +60,10 @@ impl CliEncodeCall for Rialto {
},
})
}
fn get_dispatch_info(call: &rialto_runtime::Call) -> anyhow::Result<DispatchInfo> {
Ok(call.get_dispatch_info())
}
}
impl CliChain for Rialto {
@@ -126,20 +126,12 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
}
/// Rialto node as messages source.
type RialtoSourceClient = SubstrateMessagesSource<
Rialto,
RialtoMessagesToMillau,
rialto_runtime::Runtime,
rialto_runtime::WithMillauMessagesInstance,
>;
type RialtoSourceClient =
SubstrateMessagesSource<Rialto, RialtoMessagesToMillau, rialto_runtime::WithMillauMessagesInstance>;
/// Millau node as messages target.
type MillauTargetClient = SubstrateMessagesTarget<
Millau,
RialtoMessagesToMillau,
millau_runtime::Runtime,
millau_runtime::WithRialtoMessagesInstance,
>;
type MillauTargetClient =
SubstrateMessagesTarget<Millau, RialtoMessagesToMillau, millau_runtime::WithRialtoMessagesInstance>;
/// Run Rialto-to-Millau messages sync.
pub async fn run(
@@ -14,11 +14,70 @@
// 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 crate::cli::{encode_message, CliChain};
use frame_support::weights::Weight;
use codec::Decode;
use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight};
use relay_rococo_client::Rococo;
use sp_version::RuntimeVersion;
use crate::cli::{
bridge,
encode_call::{Call, CliEncodeCall},
encode_message, CliChain,
};
/// Weight of the `system::remark` call at Rococo.
///
/// This weight is larger (x2) than actual weight at current Rooco runtime to avoid unsuccessful
/// calls in the future. But since it is used only in tests (and on test chains), this is ok.
pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000;
impl CliEncodeCall for Rococo {
fn max_extrinsic_size() -> u32 {
bp_rococo::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call {
Call::Remark { remark_payload, .. } => {
relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark(
remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(),
))
}
Call::BridgeSendMessage {
lane,
payload,
fee,
bridge_instance_index,
} => match *bridge_instance_index {
bridge::ROCOCO_TO_WOCOCO_INDEX => {
let payload = Decode::decode(&mut &*payload.0)?;
relay_rococo_client::runtime::Call::BridgeMessagesWococo(
relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message(lane.0, payload, fee.0),
)
}
_ => anyhow::bail!(
"Unsupported target bridge pallet with instance index: {}",
bridge_instance_index
),
},
_ => anyhow::bail!("The call is not supported"),
})
}
fn get_dispatch_info(call: &relay_rococo_client::runtime::Call) -> anyhow::Result<DispatchInfo> {
match *call {
relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark(_)) => {
Ok(DispatchInfo {
weight: SYSTEM_REMARK_CALL_WEIGHT,
class: DispatchClass::Normal,
pays_fee: Pays::Yes,
})
}
_ => anyhow::bail!("Unsupported Rococo call: {:?}", call),
}
}
}
impl CliChain for Rococo {
const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION;
@@ -30,7 +89,7 @@ impl CliChain for Rococo {
}
fn max_extrinsic_weight() -> Weight {
0
bp_wococo::max_extrinsic_weight()
}
fn encode_message(_message: encode_message::MessagePayload) -> Result<Self::MessagePayload, String> {
@@ -61,10 +61,9 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
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 call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo(
relay_wococo_client::runtime::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);
@@ -0,0 +1,227 @@
// 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 messages sync entrypoint.
use crate::messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce;
use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use messages_relay::message_lane::MessageLane;
use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme};
use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair};
use std::{ops::RangeInclusive, time::Duration};
/// Rococo-to-Wococo message lane.
pub type RococoMessagesToWococo =
SubstrateMessageLaneToSubstrate<Rococo, RococoSigningParams, Wococo, WococoSigningParams>;
impl SubstrateMessageLane for RococoMessagesToWococo {
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
type SourceChain = Rococo;
type TargetChain = Wococo;
fn source_transactions_author(&self) -> bp_rococo::AccountId {
(*self.source_sign.public().as_array_ref()).into()
}
fn make_messages_receiving_proof_transaction(
&self,
transaction_nonce: <Rococo as Chain>::Index,
_generated_at_block: WococoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo(
relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_delivery_proof(
proof,
relayers_state,
),
);
let genesis_hash = *self.source_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Wococo -> Rococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
bp_rococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_rococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_wococo::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
transaction_nonce: <Wococo as Chain>::Index,
_generated_at_header: RococoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof,
) -> Bytes {
let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof {
ref nonces_start,
ref nonces_end,
..
} = proof;
let messages_count = nonces_end - nonces_start + 1;
let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo(
relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof(
self.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Rococo -> Wococo delivery transaction. Weight: <unknown>/{}, size: {}/{}",
bp_wococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_wococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Rococo node as messages source.
type RococoSourceClient =
SubstrateMessagesSource<Rococo, RococoMessagesToWococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
/// Wococo node as messages target.
type WococoTargetClient =
SubstrateMessagesTarget<Wococo, RococoMessagesToWococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
/// Run Rococo-to-Wococo messages sync.
pub async fn run(
params: MessagesRelayParams<Rococo, RococoSigningParams, Wococo, WococoSigningParams>,
) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let lane = RococoMessagesToWococo {
source_client: source_client.clone(),
source_sign: params.source_sign,
target_client: params.target_client.clone(),
target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_rococo,
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_wococo::max_extrinsic_size() / 3;
// we don't know exact weights of the Wococo runtime. So to guess weights we'll be using
// weights from Rialto and then simply dividing it by x2.
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>>(
bp_wococo::max_extrinsic_weight(),
bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = (
max_messages_in_single_batch / 2,
max_messages_weight_in_single_batch / 2,
);
log::info!(
target: "bridge",
"Starting Rococo -> Wococo messages relay.\n\t\
Rococo relayer account id: {:?}\n\t\
Max messages in single transaction: {}\n\t\
Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}",
lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Rococo::AVERAGE_BLOCK_INTERVAL,
target_tick: Wococo::AVERAGE_BLOCK_INTERVAL,
reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY,
stall_timeout,
delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams {
max_unrewarded_relayer_entries_at_target: bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target: bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic,
},
},
RococoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
WOCOCO_CHAIN_ID,
params.target_to_source_headers_relay,
),
WococoTargetClient::new(
params.target_client,
lane,
lane_id,
ROCOCO_CHAIN_ID,
params.source_to_target_headers_relay,
),
relay_utils::relay_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::<
RococoMessagesToWococo,
>(&lane_id)),
params.metrics_params,
)
.standalone_metric(|registry, prefix| {
StorageProofOverheadMetric::new(
registry,
prefix,
source_client.clone(),
"rococo_storage_proof_overhead".into(),
"Rococo storage proof overhead".into(),
)
})?
.into_params(),
futures::future::pending(),
)
.await
}
@@ -14,11 +14,64 @@
// 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 crate::cli::{encode_message, CliChain};
use frame_support::weights::Weight;
use codec::Decode;
use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight};
use relay_wococo_client::Wococo;
use sp_version::RuntimeVersion;
use crate::cli::{
bridge,
encode_call::{Call, CliEncodeCall},
encode_message, CliChain,
};
impl CliEncodeCall for Wococo {
fn max_extrinsic_size() -> u32 {
bp_wococo::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call {
Call::Remark { remark_payload, .. } => {
relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark(
remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(),
))
}
Call::BridgeSendMessage {
lane,
payload,
fee,
bridge_instance_index,
} => match *bridge_instance_index {
bridge::WOCOCO_TO_ROCOCO_INDEX => {
let payload = Decode::decode(&mut &*payload.0)?;
relay_wococo_client::runtime::Call::BridgeMessagesRococo(
relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message(lane.0, payload, fee.0),
)
}
_ => anyhow::bail!(
"Unsupported target bridge pallet with instance index: {}",
bridge_instance_index
),
},
_ => anyhow::bail!("The call is not supported"),
})
}
fn get_dispatch_info(call: &relay_wococo_client::runtime::Call) -> anyhow::Result<DispatchInfo> {
match *call {
relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark(_)) => {
Ok(DispatchInfo {
weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT,
class: DispatchClass::Normal,
pays_fee: Pays::Yes,
})
}
_ => anyhow::bail!("Unsupported Rococo call: {:?}", call),
}
}
}
impl CliChain for Wococo {
const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION;
@@ -30,7 +83,7 @@ impl CliChain for Wococo {
}
fn max_extrinsic_weight() -> Weight {
0
bp_wococo::max_extrinsic_weight()
}
fn encode_message(_message: encode_message::MessagePayload) -> Result<Self::MessagePayload, String> {
@@ -67,10 +67,9 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
header: WococoSyncHeader,
proof: GrandpaJustification<bp_wococo::Header>,
) -> Bytes {
let call = bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(
header.into_inner(),
proof,
));
let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo(
relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof),
);
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
@@ -0,0 +1,227 @@
// 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/>.
//! Wococo-to-Rococo messages sync entrypoint.
use crate::messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce;
use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use messages_relay::message_lane::MessageLane;
use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme};
use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair};
use std::{ops::RangeInclusive, time::Duration};
/// Wococo-to-Rococo message lane.
pub type WococoMessagesToRococo =
SubstrateMessageLaneToSubstrate<Wococo, WococoSigningParams, Rococo, RococoSigningParams>;
impl SubstrateMessageLane for WococoMessagesToRococo {
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
type SourceChain = Wococo;
type TargetChain = Rococo;
fn source_transactions_author(&self) -> bp_wococo::AccountId {
(*self.source_sign.public().as_array_ref()).into()
}
fn make_messages_receiving_proof_transaction(
&self,
transaction_nonce: <Wococo as Chain>::Index,
_generated_at_block: RococoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo(
relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_delivery_proof(
proof,
relayers_state,
),
);
let genesis_hash = *self.source_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Rococo -> Wococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
bp_wococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_wococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_rococo::AccountId {
(*self.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
transaction_nonce: <Rococo as Chain>::Index,
_generated_at_header: WococoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof,
) -> Bytes {
let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof {
ref nonces_start,
ref nonces_end,
..
} = proof;
let messages_count = nonces_end - nonces_start + 1;
let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo(
relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof(
self.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.target_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!(
target: "bridge",
"Prepared Wococo -> Rococo delivery transaction. Weight: <unknown>/{}, size: {}/{}",
bp_rococo::max_extrinsic_weight(),
transaction.encode().len(),
bp_rococo::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Wococo node as messages source.
type WococoSourceClient =
SubstrateMessagesSource<Wococo, WococoMessagesToRococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
/// Rococo node as messages target.
type RococoTargetClient =
SubstrateMessagesTarget<Rococo, WococoMessagesToRococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
/// Run Wococo-to-Rococo messages sync.
pub async fn run(
params: MessagesRelayParams<Wococo, WococoSigningParams, Rococo, RococoSigningParams>,
) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let lane = WococoMessagesToRococo {
source_client: source_client.clone(),
source_sign: params.source_sign,
target_client: params.target_client.clone(),
target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_wococo,
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_rococo::max_extrinsic_size() / 3;
// we don't know exact weights of the Rococo runtime. So to guess weights we'll be using
// weights from Rialto and then simply dividing it by x2.
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>>(
bp_rococo::max_extrinsic_weight(),
bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = (
max_messages_in_single_batch / 2,
max_messages_weight_in_single_batch / 2,
);
log::info!(
target: "bridge",
"Starting Wococo -> Rococo messages relay.\n\t\
Wococo relayer account id: {:?}\n\t\
Max messages in single transaction: {}\n\t\
Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}",
lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Wococo::AVERAGE_BLOCK_INTERVAL,
target_tick: Rococo::AVERAGE_BLOCK_INTERVAL,
reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY,
stall_timeout,
delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams {
max_unrewarded_relayer_entries_at_target: bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target: bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic,
},
},
WococoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
ROCOCO_CHAIN_ID,
params.target_to_source_headers_relay,
),
RococoTargetClient::new(
params.target_client,
lane,
lane_id,
WOCOCO_CHAIN_ID,
params.source_to_target_headers_relay,
),
relay_utils::relay_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::<
WococoMessagesToRococo,
>(&lane_id)),
params.metrics_params,
)
.standalone_metric(|registry, prefix| {
StorageProofOverheadMetric::new(
registry,
prefix,
source_client.clone(),
"wococo_storage_proof_overhead".into(),
"Wococo storage proof overhead".into(),
)
})?
.into_params(),
futures::future::pending(),
)
.await
}
@@ -22,6 +22,8 @@ arg_enum! {
pub enum FullBridge {
MillauToRialto,
RialtoToMillau,
RococoToWococo,
WococoToRococo,
}
}
@@ -31,12 +33,16 @@ impl FullBridge {
match self {
Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX,
Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX,
Self::RococoToWococo => ROCOCO_TO_WOCOCO_INDEX,
Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX,
}
}
}
pub const RIALTO_TO_MILLAU_INDEX: u8 = 0;
pub const MILLAU_TO_RIALTO_INDEX: u8 = 0;
pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0;
pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0;
/// The macro allows executing bridge-specific code without going fully generic.
///
@@ -89,6 +95,50 @@ macro_rules! select_full_bridge {
#[allow(unused_imports)]
use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest;
$generic
}
FullBridge::RococoToWococo => {
type Source = relay_rococo_client::Rococo;
#[allow(dead_code)]
type Target = relay_wococo_client::Wococo;
// Derive-account
#[allow(unused_imports)]
use bp_wococo::derive_account_from_rococo_id as derive_account;
// Relay-messages
#[allow(unused_imports)]
use crate::chains::rococo_messages_to_wococo::run as relay_messages;
// Send-message / Estimate-fee
#[allow(unused_imports)]
use bp_wococo::TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
// Send-message
#[allow(unused_imports)]
use relay_rococo_client::runtime::rococo_to_wococo_account_ownership_digest as account_ownership_digest;
$generic
}
FullBridge::WococoToRococo => {
type Source = relay_wococo_client::Wococo;
#[allow(dead_code)]
type Target = relay_rococo_client::Rococo;
// Derive-account
#[allow(unused_imports)]
use bp_rococo::derive_account_from_wococo_id as derive_account;
// Relay-messages
#[allow(unused_imports)]
use crate::chains::wococo_messages_to_rococo::run as relay_messages;
// Send-message / Estimate-fee
#[allow(unused_imports)]
use bp_rococo::TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
// Send-message
#[allow(unused_imports)]
use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest;
$generic
}
}
@@ -17,7 +17,7 @@
use crate::cli::bridge::FullBridge;
use crate::cli::{AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId};
use crate::select_full_bridge;
use frame_support::dispatch::GetDispatchInfo;
use frame_support::weights::DispatchInfo;
use relay_substrate_client::Chain;
use structopt::StructOpt;
@@ -85,6 +85,9 @@ pub trait CliEncodeCall: Chain {
/// Encode a CLI call.
fn encode_call(call: &Call) -> anyhow::Result<Self::Call>;
/// Get dispatch info for the call.
fn get_dispatch_info(call: &Self::Call) -> anyhow::Result<DispatchInfo>;
}
impl EncodeCall {
@@ -96,7 +99,7 @@ impl EncodeCall {
let encoded = HexBytes::encode(&call);
log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call);
log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, call.get_dispatch_info().weight);
log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call)?.weight);
log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded);
Ok(encoded)
@@ -109,7 +109,9 @@ macro_rules! select_bridge {
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::initialize(init_data))
relay_wococo_client::runtime::Call::BridgeGrandpaRococo(
relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data),
)
}
$generic
@@ -121,7 +123,9 @@ macro_rules! select_bridge {
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::initialize(init_data))
relay_rococo_client::runtime::Call::BridgeGrandpaWococo(
relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize(init_data),
)
}
$generic
@@ -35,6 +35,7 @@ use structopt::StructOpt;
#[derive(StructOpt)]
pub enum RelayHeadersAndMessages {
MillauRialto(MillauRialtoHeadersAndMessages),
RococoWococo(RococoWococoHeadersAndMessages),
}
/// Parameters that have the same names across all bridges.
@@ -102,6 +103,26 @@ macro_rules! select_bridge {
use crate::chains::millau_messages_to_rialto::run as left_to_right_messages;
use crate::chains::rialto_messages_to_millau::run as right_to_left_messages;
$generic
}
RelayHeadersAndMessages::RococoWococo(_) => {
type Params = RococoWococoHeadersAndMessages;
type Left = relay_rococo_client::Rococo;
type Right = relay_wococo_client::Wococo;
type LeftToRightFinality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo;
type RightToLeftFinality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo;
type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo;
type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo;
const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH;
const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH;
use crate::chains::rococo_messages_to_wococo::run as left_to_right_messages;
use crate::chains::wococo_messages_to_rococo::run as right_to_left_messages;
$generic
}
}
@@ -111,8 +132,11 @@ macro_rules! select_bridge {
// All supported chains.
declare_chain_options!(Millau, millau);
declare_chain_options!(Rialto, rialto);
declare_chain_options!(Rococo, rococo);
declare_chain_options!(Wococo, wococo);
// All supported bridges.
declare_bridge_options!(Millau, Rialto);
declare_bridge_options!(Rococo, Wococo);
impl RelayHeadersAndMessages {
/// Run the command.
@@ -24,7 +24,7 @@ use crate::cli::{
use bp_message_dispatch::{CallOrigin, MessagePayload};
use bp_runtime::messages::DispatchFeePayment;
use codec::Encode;
use frame_support::{dispatch::GetDispatchInfo, weights::Weight};
use frame_support::weights::Weight;
use relay_substrate_client::{Chain, TransactionSignScheme};
use sp_core::{Bytes, Pair};
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
@@ -89,7 +89,7 @@ impl SendMessage {
let payload = {
let target_call_weight = prepare_call_dispatch_weight(
dispatch_weight,
ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight),
ExplicitOrMaximal::Explicit(Target::get_dispatch_info(&target_call)?.weight),
compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()),
);
let source_sender_public: MultiSigner = source_sign.public().into();
@@ -33,7 +33,6 @@ use messages_relay::{
ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState,
},
};
use pallet_bridge_messages::Config as MessagesConfig;
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf};
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId};
use sp_core::Bytes;
@@ -46,16 +45,16 @@ use std::{marker::PhantomData, ops::RangeInclusive};
pub type SubstrateMessagesProof<C> = (Weight, FromBridgedChainMessagesProof<HashOf<C>>);
/// Substrate client as Substrate messages source.
pub struct SubstrateMessagesSource<C: Chain, P: SubstrateMessageLane, R, I> {
pub struct SubstrateMessagesSource<C: Chain, P: SubstrateMessageLane, I> {
client: Client<C>,
lane: P,
lane_id: LaneId,
instance: ChainId,
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
_phantom: PhantomData<(R, I)>,
_phantom: PhantomData<I>,
}
impl<C: Chain, P: SubstrateMessageLane, R, I> SubstrateMessagesSource<C, P, R, I> {
impl<C: Chain, P: SubstrateMessageLane, I> SubstrateMessagesSource<C, P, I> {
/// Create new Substrate headers source.
pub fn new(
client: Client<C>,
@@ -75,7 +74,7 @@ impl<C: Chain, P: SubstrateMessageLane, R, I> SubstrateMessagesSource<C, P, R, I
}
}
impl<C: Chain, P: SubstrateMessageLane, R, I> Clone for SubstrateMessagesSource<C, P, R, I> {
impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesSource<C, P, I> {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
@@ -89,11 +88,10 @@ impl<C: Chain, P: SubstrateMessageLane, R, I> Clone for SubstrateMessagesSource<
}
#[async_trait]
impl<C, P, R, I> RelayClient for SubstrateMessagesSource<C, P, R, I>
impl<C, P, I> RelayClient for SubstrateMessagesSource<C, P, I>
where
C: Chain,
P: SubstrateMessageLane,
R: 'static + Send + Sync,
I: Send + Sync + Instance,
{
type Error = SubstrateError;
@@ -104,7 +102,7 @@ where
}
#[async_trait]
impl<C, P, R, I> SourceClient<P> for SubstrateMessagesSource<C, P, R, I>
impl<C, P, I> SourceClient<P> for SubstrateMessagesSource<C, P, I>
where
C: Chain,
C::Header: DeserializeOwned,
@@ -120,7 +118,6 @@ where
P::TargetChain: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
P::TargetHeaderNumber: Decode,
P::TargetHeaderHash: Decode,
R: Send + Sync + MessagesConfig<I>,
I: Send + Sync + Instance,
{
async fn state(&self) -> Result<SourceClientState<P>, SubstrateError> {
@@ -198,7 +195,7 @@ where
let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1);
let mut message_nonce = *nonces.start();
while message_nonce <= *nonces.end() {
let message_key = pallet_bridge_messages::storage_keys::message_key::<R, I>(&self.lane_id, message_nonce);
let message_key = pallet_bridge_messages::storage_keys::message_key::<I>(&self.lane_id, message_nonce);
storage_keys.push(message_key);
message_nonce += 1;
}
@@ -32,7 +32,6 @@ use messages_relay::{
message_lane::{SourceHeaderIdOf, TargetHeaderIdOf},
message_lane_loop::{TargetClient, TargetClientState},
};
use pallet_bridge_messages::Config as MessagesConfig;
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf};
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase};
use sp_core::Bytes;
@@ -46,16 +45,16 @@ pub type SubstrateMessagesReceivingProof<C> = (
);
/// Substrate client as Substrate messages target.
pub struct SubstrateMessagesTarget<C: Chain, P: SubstrateMessageLane, R, I> {
pub struct SubstrateMessagesTarget<C: Chain, P: SubstrateMessageLane, I> {
client: Client<C>,
lane: P,
lane_id: LaneId,
instance: ChainId,
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
_phantom: PhantomData<(R, I)>,
_phantom: PhantomData<I>,
}
impl<C: Chain, P: SubstrateMessageLane, R, I> SubstrateMessagesTarget<C, P, R, I> {
impl<C: Chain, P: SubstrateMessageLane, I> SubstrateMessagesTarget<C, P, I> {
/// Create new Substrate headers target.
pub fn new(
client: Client<C>,
@@ -75,7 +74,7 @@ impl<C: Chain, P: SubstrateMessageLane, R, I> SubstrateMessagesTarget<C, P, R, I
}
}
impl<C: Chain, P: SubstrateMessageLane, R, I> Clone for SubstrateMessagesTarget<C, P, R, I> {
impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesTarget<C, P, I> {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
@@ -89,11 +88,10 @@ impl<C: Chain, P: SubstrateMessageLane, R, I> Clone for SubstrateMessagesTarget<
}
#[async_trait]
impl<C, P, R, I> RelayClient for SubstrateMessagesTarget<C, P, R, I>
impl<C, P, I> RelayClient for SubstrateMessagesTarget<C, P, I>
where
C: Chain,
P: SubstrateMessageLane,
R: 'static + Send + Sync,
I: Send + Sync + Instance,
{
type Error = SubstrateError;
@@ -104,7 +102,7 @@ where
}
#[async_trait]
impl<C, P, R, I> TargetClient<P> for SubstrateMessagesTarget<C, P, R, I>
impl<C, P, I> TargetClient<P> for SubstrateMessagesTarget<C, P, I>
where
C: Chain,
C::Header: DeserializeOwned,
@@ -119,7 +117,6 @@ where
P::SourceChain: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber>,
P::SourceHeaderNumber: Decode,
P::SourceHeaderHash: Decode,
R: Send + Sync + MessagesConfig<I>,
I: Send + Sync + Instance,
{
async fn state(&self) -> Result<TargetClientState<P>, SubstrateError> {
@@ -190,7 +187,7 @@ where
id: TargetHeaderIdOf<P>,
) -> Result<(TargetHeaderIdOf<P>, P::MessagesReceivingProof), SubstrateError> {
let (id, relayers_state) = self.unrewarded_relayers_state(id).await?;
let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::<R, I>(&self.lane_id);
let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::<I>(&self.lane_id);
let proof = self
.client
.prove_storage(vec![inbound_data_key], id.1)