Refactor message relay helpers (#1234)

* refactor message relay helpers

* single standalone_metrics function

* fixed tests

* clippy + fmt

* removed commented code

* add calls tracing

* fix spelling

* cargo fmt

* -commented code

* fix build again

* post-merge build fix

* clippy + fmt
This commit is contained in:
Svyatoslav Nikolsky
2021-12-06 16:46:25 +03:00
committed by Bastian Köcher
parent 90f2b3c365
commit 4cdd959057
68 changed files with 1479 additions and 2450 deletions
+4 -3
View File
@@ -66,6 +66,7 @@ type FullClient =
type FullBackend = sc_service::TFullBackend<Block>; type FullBackend = sc_service::TFullBackend<Block>;
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>; type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
#[allow(clippy::type_complexity)]
pub fn new_partial( pub fn new_partial(
config: &Configuration, config: &Configuration,
) -> Result< ) -> Result<
@@ -89,7 +90,7 @@ pub fn new_partial(
ServiceError, ServiceError,
> { > {
if config.keystore_remote.is_some() { if config.keystore_remote.is_some() {
return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) return Err(ServiceError::Other("Remote Keystores are not supported.".into()))
} }
let telemetry = config let telemetry = config
@@ -111,7 +112,7 @@ pub fn new_partial(
let (client, backend, keystore_container, task_manager) = let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, _>( sc_service::new_full_parts::<Block, RuntimeApi, _>(
&config, config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
executor, executor,
)?; )?;
@@ -178,7 +179,7 @@ pub fn new_partial(
}) })
} }
fn remote_keystore(_url: &String) -> Result<Arc<LocalKeystore>, &'static str> { fn remote_keystore(_url: &str) -> Result<Arc<LocalKeystore>, &'static str> {
// FIXME: here would the concrete keystore be built, // FIXME: here would the concrete keystore be built,
// must return a concrete type (NOT `LocalKeystore`) that // must return a concrete type (NOT `LocalKeystore`) that
// implements `CryptoStore` and `SyncCryptoStore` // implements `CryptoStore` and `SyncCryptoStore`
+13 -12
View File
@@ -407,9 +407,9 @@ impl pallet_shift_session_manager::Config for Runtime {}
parameter_types! { parameter_types! {
pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8;
pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce =
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
// `IdentityFee` is used by Millau => we may use weight directly // `IdentityFee` is used by Millau => we may use weight directly
pub const GetDeliveryConfirmationTransactionFee: Balance = pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
@@ -875,6 +875,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use bp_runtime::Chain;
use bridge_runtime_common::messages; use bridge_runtime_common::messages;
#[test] #[test]
@@ -891,30 +892,30 @@ mod tests {
); );
let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
messages::target::maximal_incoming_message_size(bp_millau::max_extrinsic_size()), messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()),
); );
pallet_bridge_messages::ensure_able_to_receive_message::<Weights>( pallet_bridge_messages::ensure_able_to_receive_message::<Weights>(
bp_millau::max_extrinsic_size(), bp_millau::Millau::max_extrinsic_size(),
bp_millau::max_extrinsic_weight(), bp_millau::Millau::max_extrinsic_weight(),
max_incoming_message_proof_size, max_incoming_message_proof_size,
messages::target::maximal_incoming_message_dispatch_weight( messages::target::maximal_incoming_message_dispatch_weight(
bp_millau::max_extrinsic_weight(), bp_millau::Millau::max_extrinsic_weight(),
), ),
); );
let max_incoming_inbound_lane_data_proof_size = let max_incoming_inbound_lane_data_proof_size =
bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_messages::InboundLaneData::<()>::encoded_size_hint(
bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _,
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _,
) )
.unwrap_or(u32::MAX); .unwrap_or(u32::MAX);
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>( pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
bp_millau::max_extrinsic_size(), bp_millau::Millau::max_extrinsic_size(),
bp_millau::max_extrinsic_weight(), bp_millau::Millau::max_extrinsic_weight(),
max_incoming_inbound_lane_data_proof_size, max_incoming_inbound_lane_data_proof_size,
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
DbWeight::get(), DbWeight::get(),
); );
} }
@@ -23,7 +23,7 @@ use bp_messages::{
target_chain::{ProvedMessages, SourceHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain},
InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter,
}; };
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{ use frame_support::{
@@ -86,7 +86,7 @@ impl MessageBridge for WithRialtoMessageBridge {
const RELAYER_FEE_PERCENT: u32 = 10; const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID;
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME;
type ThisChain = Millau; type ThisChain = Millau;
type BridgedChain = Rialto; type BridgedChain = Rialto;
@@ -172,13 +172,13 @@ impl messages::ChainWithMessages for Rialto {
impl messages::BridgedChainWithMessages for Rialto { impl messages::BridgedChainWithMessages for Rialto {
fn maximal_extrinsic_size() -> u32 { fn maximal_extrinsic_size() -> u32 {
bp_rialto::max_extrinsic_size() bp_rialto::Rialto::max_extrinsic_size()
} }
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
// we don't want to relay too large messages + keep reserve for future upgrades // we don't want to relay too large messages + keep reserve for future upgrades
let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(
bp_rialto::max_extrinsic_weight(), bp_rialto::Rialto::max_extrinsic_weight(),
); );
// we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment`
+13 -12
View File
@@ -434,9 +434,9 @@ impl pallet_shift_session_manager::Config for Runtime {}
parameter_types! { parameter_types! {
pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8;
pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce =
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce =
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
// `IdentityFee` is used by Rialto => we may use weight directly // `IdentityFee` is used by Rialto => we may use weight directly
pub const GetDeliveryConfirmationTransactionFee: Balance = pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
@@ -1183,6 +1183,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use bp_runtime::Chain;
use bridge_runtime_common::messages; use bridge_runtime_common::messages;
#[test] #[test]
@@ -1198,30 +1199,30 @@ mod tests {
); );
let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add(
messages::target::maximal_incoming_message_size(bp_rialto::max_extrinsic_size()), messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()),
); );
pallet_bridge_messages::ensure_able_to_receive_message::<Weights>( pallet_bridge_messages::ensure_able_to_receive_message::<Weights>(
bp_rialto::max_extrinsic_size(), bp_rialto::Rialto::max_extrinsic_size(),
bp_rialto::max_extrinsic_weight(), bp_rialto::Rialto::max_extrinsic_weight(),
max_incoming_message_proof_size, max_incoming_message_proof_size,
messages::target::maximal_incoming_message_dispatch_weight( messages::target::maximal_incoming_message_dispatch_weight(
bp_rialto::max_extrinsic_weight(), bp_rialto::Rialto::max_extrinsic_weight(),
), ),
); );
let max_incoming_inbound_lane_data_proof_size = let max_incoming_inbound_lane_data_proof_size =
bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_messages::InboundLaneData::<()>::encoded_size_hint(
bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _,
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _,
) )
.unwrap_or(u32::MAX); .unwrap_or(u32::MAX);
pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>( pallet_bridge_messages::ensure_able_to_receive_confirmation::<Weights>(
bp_rialto::max_extrinsic_size(), bp_rialto::Rialto::max_extrinsic_size(),
bp_rialto::max_extrinsic_weight(), bp_rialto::Rialto::max_extrinsic_weight(),
max_incoming_inbound_lane_data_proof_size, max_incoming_inbound_lane_data_proof_size,
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
DbWeight::get(), DbWeight::get(),
); );
} }
@@ -23,7 +23,7 @@ use bp_messages::{
target_chain::{ProvedMessages, SourceHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain},
InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter,
}; };
use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{ use frame_support::{
@@ -86,7 +86,7 @@ impl MessageBridge for WithMillauMessageBridge {
const RELAYER_FEE_PERCENT: u32 = 10; const RELAYER_FEE_PERCENT: u32 = 10;
const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID;
const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID;
const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME;
type ThisChain = Rialto; type ThisChain = Rialto;
type BridgedChain = Millau; type BridgedChain = Millau;
@@ -170,13 +170,13 @@ impl messages::ChainWithMessages for Millau {
impl messages::BridgedChainWithMessages for Millau { impl messages::BridgedChainWithMessages for Millau {
fn maximal_extrinsic_size() -> u32 { fn maximal_extrinsic_size() -> u32 {
bp_millau::max_extrinsic_size() bp_millau::Millau::max_extrinsic_size()
} }
fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive<Weight> {
// we don't want to relay too large messages + keep reserve for future upgrades // we don't want to relay too large messages + keep reserve for future upgrades
let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(
bp_millau::max_extrinsic_weight(), bp_millau::Millau::max_extrinsic_weight(),
); );
// we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment`
+7
View File
@@ -106,6 +106,13 @@ impl Chain for TestBridgedChain {
type Balance = u64; type Balance = u64;
type Index = u64; type Index = u64;
type Signature = Signature; type Signature = Signature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
} }
pub fn run_test<T>(test: impl FnOnce() -> T) -> T { pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
+7
View File
@@ -142,6 +142,13 @@ impl bp_runtime::Chain for BridgedChain {
type Balance = BridgedBalance; type Balance = BridgedBalance;
type Index = u64; type Index = u64;
type Signature = BridgedAccountSignature; type Signature = BridgedAccountSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
} }
pub struct TestMessagesBridge; pub struct TestMessagesBridge;
+2 -2
View File
@@ -81,8 +81,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000;
/// conditions. /// conditions.
pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; pub const SESSION_LENGTH: BlockNumber = time_units::HOURS;
/// Name of the With-Polkadot messages pallet instance in the Kusama runtime. /// Name of the With-Kusama messages pallet instance that is deployed at bridged chains.
pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages";
/// Name of the DOT->KSM conversion rate stored in the Kusama runtime. /// Name of the DOT->KSM conversion rate stored in the Kusama runtime.
pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str =
+19 -17
View File
@@ -68,11 +68,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/// Represents the portion of a block that will be used by Normal extrinsics. /// Represents the portion of a block that will be used by Normal extrinsics.
pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// Maximal number of unrewarded relayer entries at inbound lane. /// Maximal number of unrewarded relayer entries in Millau confirmation transaction.
pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128;
/// Maximal number of unconfirmed messages at inbound lane. /// Maximal number of unconfirmed messages in Millau confirmation transaction.
pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128;
/// Weight of single regular message delivery transaction on Millau chain. /// Weight of single regular message delivery transaction on Millau chain.
/// ///
@@ -172,6 +172,17 @@ impl Chain for Millau {
type Balance = Balance; type Balance = Balance;
type Index = Index; type Index = Index;
type Signature = Signature; type Signature = Signature;
fn max_extrinsic_size() -> u32 {
*BlockLength::get().max.get(DispatchClass::Normal)
}
fn max_extrinsic_weight() -> Weight {
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
} }
/// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation.
@@ -246,21 +257,12 @@ frame_support::parameter_types! {
.build_or_panic(); .build_or_panic();
} }
/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. /// Name of the With-Millau messages pallet instance that is deployed at bridged chains.
pub fn max_extrinsic_weight() -> Weight { pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages";
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. /// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime.
pub fn max_extrinsic_size() -> u32 { pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate";
*BlockLength::get().max.get(DispatchClass::Normal)
}
/// Name of the With-Rialto messages pallet instance in the Millau runtime.
pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages";
/// Name of the With-Rialto token swap pallet instance in the Millau runtime. /// Name of the With-Rialto token swap pallet instance in the Millau runtime.
pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap";
+2 -2
View File
@@ -81,8 +81,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000;
/// conditions. /// conditions.
pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS;
/// Name of the With-Kusama messages pallet instance in the Polkadot runtime. /// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains.
pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages";
/// Name of the KSM->DOT conversion rate stored in the Polkadot runtime. /// Name of the KSM->DOT conversion rate stored in the Polkadot runtime.
pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str =
@@ -92,6 +92,17 @@ impl Chain for RialtoParachain {
type Balance = Balance; type Balance = Balance;
type Index = Index; type Index = Index;
type Signature = Signature; type Signature = Signature;
fn max_extrinsic_size() -> u32 {
*BlockLength::get().max.get(DispatchClass::Normal)
}
fn max_extrinsic_weight() -> Weight {
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
} }
frame_support::parameter_types! { frame_support::parameter_types! {
@@ -113,16 +124,3 @@ frame_support::parameter_types! {
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic(); .build_or_panic();
} }
/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use.
pub fn max_extrinsic_weight() -> Weight {
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires.
pub fn max_extrinsic_size() -> u32 {
*BlockLength::get().max.get(DispatchClass::Normal)
}
+19 -18
View File
@@ -59,11 +59,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/// Represents the portion of a block that will be used by Normal extrinsics. /// Represents the portion of a block that will be used by Normal extrinsics.
pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// Maximal number of unrewarded relayer entries at inbound lane. /// Maximal number of unrewarded relayer entries in Rialto confirmation transaction.
pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024;
/// Maximal number of unconfirmed messages at inbound lane. /// Maximal number of unconfirmed messages in Rialto confirmation transaction.
pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024;
/// Weight of single regular message delivery transaction on Rialto chain. /// Weight of single regular message delivery transaction on Rialto chain.
/// ///
@@ -171,6 +171,17 @@ impl Chain for Rialto {
type Balance = Balance; type Balance = Balance;
type Index = Index; type Index = Index;
type Signature = Signature; type Signature = Signature;
fn max_extrinsic_size() -> u32 {
*BlockLength::get().max.get(DispatchClass::Normal)
}
fn max_extrinsic_weight() -> Weight {
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
} }
/// Convert a 256-bit hash into an AccountId. /// Convert a 256-bit hash into an AccountId.
@@ -215,21 +226,11 @@ frame_support::parameter_types! {
.build_or_panic(); .build_or_panic();
} }
/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. /// Name of the With-Rialto messages pallet instance that is deployed at bridged chains.
pub fn max_extrinsic_weight() -> Weight { pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages";
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. /// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto runtime.
pub fn max_extrinsic_size() -> u32 { pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate";
*BlockLength::get().max.get(DispatchClass::Normal)
}
/// Name of the With-Millau messages pallet instance in the Rialto runtime.
pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages";
/// Name of the parachain registrar pallet in the Rialto runtime. /// Name of the parachain registrar pallet in the Rialto runtime.
pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar";
+2 -2
View File
@@ -74,8 +74,8 @@ pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount<AccountId>) -
AccountIdConverter::convert(encoded_id) AccountIdConverter::convert(encoded_id)
} }
/// Name of the With-Wococo messages pallet instance in the Rococo runtime. /// Name of the With-Rococo messages pallet instance that is deployed at bridged chains.
pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages";
/// Name of the `RococoFinalityApi::best_finalized` runtime method. /// Name of the `RococoFinalityApi::best_finalized` runtime method.
pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized";
+2 -2
View File
@@ -39,8 +39,8 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount<AccountId>) -
AccountIdConverter::convert(encoded_id) AccountIdConverter::convert(encoded_id)
} }
/// Name of the With-Rococo messages pallet instance in the Wococo runtime. /// Name of the With-Wococo messages pallet instance that is deployed at bridged chains.
pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages";
/// Name of the `WococoFinalityApi::best_finalized` runtime method. /// Name of the `WococoFinalityApi::best_finalized` runtime method.
pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized";
+13 -16
View File
@@ -115,31 +115,17 @@ parameter_types! {
.build_or_panic(); .build_or_panic();
} }
/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can
/// use.
pub fn max_extrinsic_weight() -> Weight {
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
/// Get the maximum length in bytes that a Normal extrinsic on the Polkadot-like chain requires.
pub fn max_extrinsic_size() -> u32 {
*BlockLength::get().max.get(DispatchClass::Normal)
}
// TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 // TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78
/// Maximal number of messages in single delivery transaction. /// Maximal number of messages in single delivery transaction.
pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128;
/// Maximal number of unrewarded relayer entries at inbound lane. /// Maximal number of unrewarded relayer entries at inbound lane.
pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128;
// TODO [#438] should be selected keeping in mind: // TODO [#438] should be selected keeping in mind:
// finality delay on both chains + reward payout cost + messages throughput. // finality delay on both chains + reward payout cost + messages throughput.
/// Maximal number of unconfirmed messages at inbound lane. /// Maximal number of unconfirmed messages at inbound lane.
pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192;
// One important thing about weight-related constants here is that actually we may have // One important thing about weight-related constants here is that actually we may have
// different weights on different Polkadot-like chains. But now all deployments are // different weights on different Polkadot-like chains. But now all deployments are
@@ -361,6 +347,17 @@ impl Chain for PolkadotLike {
type Balance = Balance; type Balance = Balance;
type Index = Index; type Index = Index;
type Signature = Signature; type Signature = Signature;
fn max_extrinsic_size() -> u32 {
*BlockLength::get().max.get(DispatchClass::Normal)
}
fn max_extrinsic_weight() -> Weight {
BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.unwrap_or(Weight::MAX)
}
} }
/// Convert a 256-bit hash into an AccountId. /// Convert a 256-bit hash into an AccountId.
+6 -1
View File
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use frame_support::Parameter; use frame_support::{weights::Weight, Parameter};
use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
use sp_runtime::{ use sp_runtime::{
traits::{ traits::{
@@ -120,6 +120,11 @@ pub trait Chain: Send + Sync + 'static {
+ Copy; + Copy;
/// Signature type, used on this chain. /// Signature type, used on this chain.
type Signature: Parameter + Verify; type Signature: Parameter + Verify;
/// Get the maximum size (in bytes) of a Normal extrinsic at this chain.
fn max_extrinsic_size() -> u32;
/// Get the maximum weight (compute time) that a Normal extrinsic at this chain can use.
fn max_extrinsic_weight() -> Weight;
} }
/// Block number used by the chain. /// Block number used by the chain.
@@ -17,8 +17,6 @@
use codec::Decode; use codec::Decode;
use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight};
use relay_kusama_client::Kusama; use relay_kusama_client::Kusama;
use sp_core::storage::StorageKey;
use sp_runtime::{FixedPointNumber, FixedU128};
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
use crate::cli::{ use crate::cli::{
@@ -33,14 +31,7 @@ use crate::cli::{
/// calls in the future. But since it is used only in tests (and on test chains), this is ok. /// 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; pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000;
/// Id of Kusama token that is used to fetch token price.
pub(crate) const TOKEN_ID: &str = "kusama";
impl CliEncodeCall for Kusama { impl CliEncodeCall for Kusama {
fn max_extrinsic_size() -> u32 {
bp_kusama::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System(
@@ -93,24 +84,9 @@ impl CliChain for Kusama {
42 42
} }
fn max_extrinsic_weight() -> Weight {
bp_kusama::max_extrinsic_weight()
}
fn encode_message( fn encode_message(
_message: encode_message::MessagePayload, _message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
anyhow::bail!("Sending messages from Kusama is not yet supported.") anyhow::bail!("Sending messages from Kusama is not yet supported.")
} }
} }
/// Storage key and initial value of Polkadot -> Kusama conversion rate.
pub(crate) fn polkadot_to_kusama_conversion_rate_params() -> (StorageKey, FixedU128) {
(
bp_runtime::storage_parameter_key(
bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME,
),
// starting relay before this parameter will be set to some value may cause troubles
FixedU128::from_inner(FixedU128::DIV),
)
}
@@ -17,7 +17,7 @@
//! Kusama-to-Polkadot headers sync entrypoint. //! Kusama-to-Polkadot headers sync entrypoint.
use sp_core::Pair; use sp_core::Pair;
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams};
/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat
/// relay as gone wild. /// relay as gone wild.
@@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot {
); );
relay_substrate_client::guard::abort_when_account_balance_decreased( relay_substrate_client::guard::abort_when_account_balance_decreased(
target_client.clone(), target_client.clone(),
transaction_params.transactions_signer.public().into(), transaction_params.signer.public().into(),
MAXIMAL_BALANCE_DECREASE_PER_DAY, MAXIMAL_BALANCE_DECREASE_PER_DAY,
); );
} }
@@ -16,284 +16,49 @@
//! Kusama-to-Polkadot messages sync entrypoint. //! Kusama-to-Polkadot messages sync entrypoint.
use std::ops::RangeInclusive;
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight; use frame_support::weights::Weight;
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_messages::MessageNonce; use messages_relay::relay_strategy::MixStrategy;
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use relay_kusama_client::Kusama;
use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_polkadot_client::Polkadot;
use relay_kusama_client::{ use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction};
HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, use substrate_relay_helper::messages_lane::SubstrateMessageLane;
};
use relay_polkadot_client::{
HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams,
};
use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction};
use substrate_relay_helper::{
messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics,
SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
},
messages_source::SubstrateMessagesSource,
messages_target::SubstrateMessagesTarget,
STALL_TIMEOUT,
};
/// Kusama-to-Polkadot message lane. /// Description of Kusama -> Polkadot messages bridge.
pub type MessageLaneKusamaMessagesToPolkadot = #[derive(Clone, Debug)]
SubstrateMessageLaneToSubstrate<Kusama, KusamaSigningParams, Polkadot, PolkadotSigningParams>; pub struct KusamaMessagesToPolkadot;
substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!(
#[derive(Clone)] KusamaMessagesToPolkadot,
pub struct KusamaMessagesToPolkadot { KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder,
message_lane: MessageLaneKusamaMessagesToPolkadot, relay_polkadot_client::runtime::Call::BridgeKusamaMessages,
} relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof
);
substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!(
KusamaMessagesToPolkadot,
KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder,
relay_kusama_client::runtime::Call::BridgePolkadotMessages,
relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof
);
impl SubstrateMessageLane for KusamaMessagesToPolkadot { impl SubstrateMessageLane for KusamaMessagesToPolkadot {
type MessageLane = MessageLaneKusamaMessagesToPolkadot; const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME);
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME);
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str =
bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str =
bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD;
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str =
bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME;
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str =
bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight =
bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
type SourceChain = Kusama; type SourceChain = Kusama;
type TargetChain = Polkadot; type TargetChain = Polkadot;
fn source_transactions_author(&self) -> bp_kusama::AccountId { type SourceTransactionSignScheme = Kusama;
(*self.message_lane.source_sign.public().as_array_ref()).into() type TargetTransactionSignScheme = Polkadot;
}
fn make_messages_receiving_proof_transaction( type ReceiveMessagesProofCallBuilder = KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder;
&self, type ReceiveMessagesDeliveryProofCallBuilder =
best_block_id: KusamaHeaderId, KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder;
transaction_nonce: bp_runtime::IndexOf<Kusama>,
_generated_at_block: PolkadotHeaderId,
proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages(
relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof(
proof,
relayers_state,
),
);
let genesis_hash = *self.message_lane.source_client.genesis_hash();
let transaction = Kusama::sign_transaction(
genesis_hash,
&self.message_lane.source_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.source_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Polkadot -> Kusama confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
bp_kusama::max_extrinsic_weight(),
transaction.encode().len(),
bp_kusama::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_polkadot::AccountId { type RelayStrategy = MixStrategy;
(*self.message_lane.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
best_block_id: PolkadotHeaderId,
transaction_nonce: bp_runtime::IndexOf<Polkadot>,
_generated_at_header: KusamaHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane 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_polkadot_client::runtime::Call::BridgeKusamaMessages(
relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof(
self.message_lane.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Polkadot::sign_transaction(
genesis_hash,
&self.message_lane.target_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.target_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Kusama -> Polkadot delivery transaction. Weight: <unknown>/{}, size: {}/{}",
bp_polkadot::max_extrinsic_weight(),
transaction.encode().len(),
bp_polkadot::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Kusama node as messages source.
type KusamaSourceClient = SubstrateMessagesSource<KusamaMessagesToPolkadot>;
/// Polkadot node as messages target.
type PolkadotTargetClient = SubstrateMessagesTarget<KusamaMessagesToPolkadot>;
/// Run Kusama-to-Polkadot messages sync.
pub async fn run(
params: MessagesRelayParams<
Kusama,
KusamaSigningParams,
Polkadot,
PolkadotSigningParams,
MixStrategy,
>,
) -> anyhow::Result<()> {
let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
params.source_transactions_mortality,
params.target_transactions_mortality,
Kusama::AVERAGE_BLOCK_INTERVAL,
Polkadot::AVERAGE_BLOCK_INTERVAL,
STALL_TIMEOUT,
);
let relayer_id_at_kusama = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let target_client = params.target_client;
let lane = KusamaMessagesToPolkadot {
message_lane: SubstrateMessageLaneToSubstrate {
source_client: source_client.clone(),
source_sign: params.source_sign,
source_transactions_mortality: params.source_transactions_mortality,
target_client: target_client.clone(),
target_sign: params.target_sign,
target_transactions_mortality: params.target_transactions_mortality,
relayer_id_at_source: relayer_id_at_kusama,
},
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_polkadot::max_extrinsic_size() / 3;
// we don't know exact weights of the Polkadot 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_polkadot::max_extrinsic_weight(),
bp_polkadot::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 Kusama -> Polkadot messages relay.\n\t\
Kusama 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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transactions_mortality,
params.target_transactions_mortality,
stall_timeout,
);
let standalone_metrics = params
.standalone_metrics
.map(Ok)
.unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?;
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Kusama::AVERAGE_BLOCK_INTERVAL,
target_tick: Polkadot::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_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target:
bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relay_strategy: params.relay_strategy,
},
},
KusamaSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
params.target_to_source_headers_relay,
),
PolkadotTargetClient::new(
target_client,
lane,
lane_id,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Create standalone metrics for the Kusama -> Polkadot messages loop.
pub(crate) fn standalone_metrics(
source_client: Client<Kusama>,
target_client: Client<Polkadot>,
) -> anyhow::Result<StandaloneMessagesMetrics<Kusama, Polkadot>> {
substrate_relay_helper::messages_lane::standalone_metrics(
source_client,
target_client,
Some(crate::chains::kusama::TOKEN_ID),
Some(crate::chains::polkadot::TOKEN_ID),
Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()),
Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()),
)
} }
/// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage. /// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage.
@@ -26,24 +26,11 @@ use crate::cli::{
use anyhow::anyhow; use anyhow::anyhow;
use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Decode; use codec::Decode;
use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use frame_support::weights::{DispatchInfo, GetDispatchInfo};
use relay_millau_client::Millau; use relay_millau_client::Millau;
use sp_core::storage::StorageKey;
use sp_runtime::FixedU128;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we
// want to test our code that is intended to work with real-value chains. So to keep it close to
// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer).
/// The identifier of token, which value is associated with Millau token value by relayer.
pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::kusama::TOKEN_ID;
impl CliEncodeCall for Millau { impl CliEncodeCall for Millau {
fn max_extrinsic_size() -> u32 {
bp_millau::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Raw { data } => Decode::decode(&mut &*data.0)?, Call::Raw { data } => Decode::decode(&mut &*data.0)?,
@@ -96,10 +83,6 @@ impl CliChain for Millau {
millau_runtime::SS58Prefix::get() as u16 millau_runtime::SS58Prefix::get() as u16
} }
fn max_extrinsic_weight() -> Weight {
bp_millau::max_extrinsic_weight()
}
// TODO [#854|#843] support multiple bridges? // TODO [#854|#843] support multiple bridges?
fn encode_message( fn encode_message(
message: encode_message::MessagePayload, message: encode_message::MessagePayload,
@@ -132,11 +115,3 @@ impl CliChain for Millau {
} }
} }
} }
/// Storage key and initial value of Rialto -> Millau conversion rate.
pub(crate) fn rialto_to_millau_conversion_rate_params() -> (StorageKey, FixedU128) {
(
StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()),
millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE,
)
}
@@ -16,279 +16,46 @@
//! Millau-to-Rialto messages sync entrypoint. //! Millau-to-Rialto messages sync entrypoint.
use std::ops::RangeInclusive;
use codec::Encode; use codec::Encode;
use frame_support::dispatch::GetDispatchInfo;
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_messages::MessageNonce; use messages_relay::relay_strategy::MixStrategy;
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use relay_millau_client::Millau;
use frame_support::weights::Weight; use relay_rialto_client::Rialto;
use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction};
use relay_millau_client::{ use substrate_relay_helper::messages_lane::{
HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder,
}; SubstrateMessageLane,
use relay_rialto_client::{
HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams,
};
use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
use substrate_relay_helper::{
messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics,
SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
},
messages_source::SubstrateMessagesSource,
messages_target::SubstrateMessagesTarget,
STALL_TIMEOUT,
}; };
/// Millau-to-Rialto message lane. /// Description of Millau -> Rialto messages bridge.
pub type MessageLaneMillauMessagesToRialto = #[derive(Clone, Debug)]
SubstrateMessageLaneToSubstrate<Millau, MillauSigningParams, Rialto, RialtoSigningParams>; pub struct MillauMessagesToRialto;
#[derive(Clone)]
pub struct MillauMessagesToRialto {
message_lane: MessageLaneMillauMessagesToRialto,
}
impl SubstrateMessageLane for MillauMessagesToRialto { impl SubstrateMessageLane for MillauMessagesToRialto {
type MessageLane = MessageLaneMillauMessagesToRialto; const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME);
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME);
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str =
bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str =
bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME;
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight =
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
type SourceChain = Millau; type SourceChain = Millau;
type TargetChain = Rialto; type TargetChain = Rialto;
fn source_transactions_author(&self) -> bp_millau::AccountId { type SourceTransactionSignScheme = Millau;
(*self.message_lane.source_sign.public().as_array_ref()).into() type TargetTransactionSignScheme = Rialto;
}
fn make_messages_receiving_proof_transaction( type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder<
&self, Self,
best_block_id: MillauHeaderId, rialto_runtime::Runtime,
transaction_nonce: IndexOf<Millau>, rialto_runtime::WithMillauMessagesInstance,
_generated_at_block: RialtoHeaderId, >;
proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof, type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder<
) -> Bytes { Self,
let (relayers_state, proof) = proof; millau_runtime::Runtime,
let call: millau_runtime::Call = millau_runtime::WithRialtoMessagesInstance,
millau_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } >;
.into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.message_lane.source_client.genesis_hash();
let transaction = Millau::sign_transaction(
genesis_hash,
&self.message_lane.source_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.source_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_millau::max_extrinsic_weight(),
transaction.encode().len(),
bp_millau::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_rialto::AccountId { type RelayStrategy = MixStrategy;
(*self.message_lane.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
best_block_id: RialtoHeaderId,
transaction_nonce: IndexOf<Rialto>,
_generated_at_header: MillauHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane 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: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof {
relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(),
proof,
messages_count: messages_count as _,
dispatch_weight,
}
.into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Rialto::sign_transaction(
genesis_hash,
&self.message_lane.target_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.target_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_rialto::max_extrinsic_weight(),
transaction.encode().len(),
bp_rialto::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Millau node as messages source.
type MillauSourceClient = SubstrateMessagesSource<MillauMessagesToRialto>;
/// Rialto node as messages target.
type RialtoTargetClient = SubstrateMessagesTarget<MillauMessagesToRialto>;
/// Run Millau-to-Rialto messages sync.
pub async fn run(
params: MessagesRelayParams<
Millau,
MillauSigningParams,
Rialto,
RialtoSigningParams,
MixStrategy,
>,
) -> anyhow::Result<()> {
let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
params.source_transactions_mortality,
params.target_transactions_mortality,
Millau::AVERAGE_BLOCK_INTERVAL,
Rialto::AVERAGE_BLOCK_INTERVAL,
STALL_TIMEOUT,
);
let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let target_client = params.target_client;
let lane = MillauMessagesToRialto {
message_lane: SubstrateMessageLaneToSubstrate {
source_client: source_client.clone(),
source_sign: params.source_sign,
source_transactions_mortality: params.source_transactions_mortality,
target_client: target_client.clone(),
target_sign: params.target_sign,
target_transactions_mortality: params.target_transactions_mortality,
relayer_id_at_source: relayer_id_at_millau,
},
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3;
// TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390
let (max_messages_in_single_batch, max_messages_weight_in_single_batch) =
select_delivery_transaction_limits::<
pallet_bridge_messages::weights::RialtoWeight<millau_runtime::Runtime>,
>(
bp_rialto::max_extrinsic_weight(),
bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
log::info!(
target: "bridge",
"Starting Millau -> Rialto messages relay.\n\t\
Millau 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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transactions_mortality,
params.target_transactions_mortality,
stall_timeout,
);
let standalone_metrics = params
.standalone_metrics
.map(Ok)
.unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?;
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Millau::AVERAGE_BLOCK_INTERVAL,
target_tick: Rialto::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_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target:
bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relay_strategy: params.relay_strategy,
},
},
MillauSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
params.target_to_source_headers_relay,
),
RialtoTargetClient::new(
target_client,
lane,
lane_id,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Create standalone metrics for the Millau -> Rialto messages loop.
pub(crate) fn standalone_metrics(
source_client: Client<Millau>,
target_client: Client<Rialto>,
) -> anyhow::Result<StandaloneMessagesMetrics<Millau, Rialto>> {
substrate_relay_helper::messages_lane::standalone_metrics(
source_client,
target_client,
Some(crate::chains::millau::ASSOCIATED_TOKEN_ID),
Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID),
Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()),
Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()),
)
} }
/// Update Rialto -> Millau conversion rate, stored in Millau runtime storage. /// Update Rialto -> Millau conversion rate, stored in Millau runtime storage.
@@ -43,6 +43,7 @@ mod wococo;
mod tests { mod tests {
use crate::cli::{encode_call, send_message}; use crate::cli::{encode_call, send_message};
use bp_messages::source_chain::TargetHeaderChain; use bp_messages::source_chain::TargetHeaderChain;
use bp_runtime::Chain as _;
use codec::Encode; use codec::Encode;
use frame_support::dispatch::GetDispatchInfo; use frame_support::dispatch::GetDispatchInfo;
use relay_millau_client::Millau; use relay_millau_client::Millau;
@@ -102,8 +103,8 @@ mod tests {
use rialto_runtime::millau_messages::Millau; use rialto_runtime::millau_messages::Millau;
let maximal_remark_size = encode_call::compute_maximal_message_arguments_size( let maximal_remark_size = encode_call::compute_maximal_message_arguments_size(
bp_rialto::max_extrinsic_size(), bp_rialto::Rialto::max_extrinsic_size(),
bp_millau::max_extrinsic_size(), bp_millau::Millau::max_extrinsic_size(),
); );
let call: millau_runtime::Call = let call: millau_runtime::Call =
@@ -135,8 +136,8 @@ mod tests {
fn maximal_size_remark_to_rialto_is_generated_correctly() { fn maximal_size_remark_to_rialto_is_generated_correctly() {
assert!( assert!(
bridge_runtime_common::messages::target::maximal_incoming_message_size( bridge_runtime_common::messages::target::maximal_incoming_message_size(
bp_rialto::max_extrinsic_size() bp_rialto::Rialto::max_extrinsic_size()
) > bp_millau::max_extrinsic_size(), ) > bp_millau::Millau::max_extrinsic_size(),
"We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large",
) )
} }
@@ -146,7 +147,7 @@ mod tests {
use rialto_runtime::millau_messages::Millau; use rialto_runtime::millau_messages::Millau;
let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight(
bp_millau::max_extrinsic_weight(), bp_millau::Millau::max_extrinsic_weight(),
); );
let call: millau_runtime::Call = let call: millau_runtime::Call =
rialto_runtime::SystemCall::remark { remark: vec![] }.into(); rialto_runtime::SystemCall::remark { remark: vec![] }.into();
@@ -175,7 +176,7 @@ mod tests {
use millau_runtime::rialto_messages::Rialto; use millau_runtime::rialto_messages::Rialto;
let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight(
bp_rialto::max_extrinsic_weight(), bp_rialto::Rialto::max_extrinsic_weight(),
); );
let call: rialto_runtime::Call = let call: rialto_runtime::Call =
millau_runtime::SystemCall::remark { remark: vec![] }.into(); millau_runtime::SystemCall::remark { remark: vec![] }.into();
@@ -17,8 +17,6 @@
use codec::Decode; use codec::Decode;
use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight};
use relay_polkadot_client::Polkadot; use relay_polkadot_client::Polkadot;
use sp_core::storage::StorageKey;
use sp_runtime::{FixedPointNumber, FixedU128};
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
use crate::cli::{ use crate::cli::{
@@ -33,14 +31,7 @@ use crate::cli::{
/// calls in the future. But since it is used only in tests (and on test chains), this is ok. /// 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; pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000;
/// Id of Polkadot token that is used to fetch token price.
pub(crate) const TOKEN_ID: &str = "polkadot";
impl CliEncodeCall for Polkadot { impl CliEncodeCall for Polkadot {
fn max_extrinsic_size() -> u32 {
bp_polkadot::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System(
@@ -93,24 +84,9 @@ impl CliChain for Polkadot {
42 42
} }
fn max_extrinsic_weight() -> Weight {
bp_polkadot::max_extrinsic_weight()
}
fn encode_message( fn encode_message(
_message: encode_message::MessagePayload, _message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
anyhow::bail!("Sending messages from Polkadot is not yet supported.") anyhow::bail!("Sending messages from Polkadot is not yet supported.")
} }
} }
/// Storage key and initial value of Kusama -> Polkadot conversion rate.
pub(crate) fn kusama_to_polkadot_conversion_rate_params() -> (StorageKey, FixedU128) {
(
bp_runtime::storage_parameter_key(
bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME,
),
// starting relay before this parameter will be set to some value may cause troubles
FixedU128::from_inner(FixedU128::DIV),
)
}
@@ -17,7 +17,7 @@
//! Polkadot-to-Kusama headers sync entrypoint. //! Polkadot-to-Kusama headers sync entrypoint.
use sp_core::Pair; use sp_core::Pair;
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams};
/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat
/// relay as gone wild. /// relay as gone wild.
@@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama {
); );
relay_substrate_client::guard::abort_when_account_balance_decreased( relay_substrate_client::guard::abort_when_account_balance_decreased(
target_client.clone(), target_client.clone(),
transaction_params.transactions_signer.public().into(), transaction_params.signer.public().into(),
MAXIMAL_BALANCE_DECREASE_PER_DAY, MAXIMAL_BALANCE_DECREASE_PER_DAY,
); );
} }
@@ -16,283 +16,49 @@
//! Polkadot-to-Kusama messages sync entrypoint. //! Polkadot-to-Kusama messages sync entrypoint.
use std::ops::RangeInclusive;
use codec::Encode; use codec::Encode;
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_messages::MessageNonce;
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use frame_support::weights::Weight; use frame_support::weights::Weight;
use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use messages_relay::relay_strategy::MixStrategy;
use relay_kusama_client::{ use relay_kusama_client::Kusama;
HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, use relay_polkadot_client::Polkadot;
}; use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction};
use relay_polkadot_client::{ use substrate_relay_helper::messages_lane::SubstrateMessageLane;
HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams,
};
use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction};
use substrate_relay_helper::{
messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics,
SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
},
messages_source::SubstrateMessagesSource,
messages_target::SubstrateMessagesTarget,
STALL_TIMEOUT,
};
/// Polkadot-to-Kusama message lane. /// Description of Polkadot -> Kusama messages bridge.
pub type MessageLanePolkadotMessagesToKusama = #[derive(Clone, Debug)]
SubstrateMessageLaneToSubstrate<Polkadot, PolkadotSigningParams, Kusama, KusamaSigningParams>; pub struct PolkadotMessagesToKusama;
substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!(
#[derive(Clone)] PolkadotMessagesToKusama,
pub struct PolkadotMessagesToKusama { PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder,
message_lane: MessageLanePolkadotMessagesToKusama, relay_kusama_client::runtime::Call::BridgePolkadotMessages,
} relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof
);
substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!(
PolkadotMessagesToKusama,
PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder,
relay_polkadot_client::runtime::Call::BridgeKusamaMessages,
relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof
);
impl SubstrateMessageLane for PolkadotMessagesToKusama { impl SubstrateMessageLane for PolkadotMessagesToKusama {
type MessageLane = MessageLanePolkadotMessagesToKusama; const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME);
bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME);
bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str =
bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str =
bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD;
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str =
bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME;
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str =
bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight =
bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
type SourceChain = Polkadot; type SourceChain = Polkadot;
type TargetChain = Kusama; type TargetChain = Kusama;
fn source_transactions_author(&self) -> bp_polkadot::AccountId { type SourceTransactionSignScheme = Polkadot;
(*self.message_lane.source_sign.public().as_array_ref()).into() type TargetTransactionSignScheme = Kusama;
}
fn make_messages_receiving_proof_transaction( type ReceiveMessagesProofCallBuilder = PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder;
&self, type ReceiveMessagesDeliveryProofCallBuilder =
best_block_id: PolkadotHeaderId, PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder;
transaction_nonce: bp_runtime::IndexOf<Polkadot>,
_generated_at_block: KusamaHeaderId,
proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes {
let (relayers_state, proof) = proof;
let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages(
relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof(
proof,
relayers_state,
),
);
let genesis_hash = *self.message_lane.source_client.genesis_hash();
let transaction = Polkadot::sign_transaction(
genesis_hash,
&self.message_lane.source_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.source_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Kusama -> Polkadot confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
bp_polkadot::max_extrinsic_weight(),
transaction.encode().len(),
bp_polkadot::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_kusama::AccountId { type RelayStrategy = MixStrategy;
(*self.message_lane.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
best_block_id: KusamaHeaderId,
transaction_nonce: bp_runtime::IndexOf<Kusama>,
_generated_at_header: PolkadotHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane 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_kusama_client::runtime::Call::BridgePolkadotMessages(
relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof(
self.message_lane.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Kusama::sign_transaction(
genesis_hash,
&self.message_lane.target_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.target_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Polkadot -> Kusama delivery transaction. Weight: <unknown>/{}, size: {}/{}",
bp_kusama::max_extrinsic_weight(),
transaction.encode().len(),
bp_kusama::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Polkadot node as messages source.
type PolkadotSourceClient = SubstrateMessagesSource<PolkadotMessagesToKusama>;
/// Kusama node as messages target.
type KusamaTargetClient = SubstrateMessagesTarget<PolkadotMessagesToKusama>;
/// Run Polkadot-to-Kusama messages sync.
pub async fn run(
params: MessagesRelayParams<
Polkadot,
PolkadotSigningParams,
Kusama,
KusamaSigningParams,
MixStrategy,
>,
) -> anyhow::Result<()> {
let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
params.source_transactions_mortality,
params.target_transactions_mortality,
Polkadot::AVERAGE_BLOCK_INTERVAL,
Kusama::AVERAGE_BLOCK_INTERVAL,
STALL_TIMEOUT,
);
let relayer_id_at_polkadot = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let target_client = params.target_client;
let lane = PolkadotMessagesToKusama {
message_lane: SubstrateMessageLaneToSubstrate {
source_client: source_client.clone(),
source_sign: params.source_sign,
source_transactions_mortality: params.source_transactions_mortality,
target_client: target_client.clone(),
target_sign: params.target_sign,
target_transactions_mortality: params.target_transactions_mortality,
relayer_id_at_source: relayer_id_at_polkadot,
},
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_kusama::max_extrinsic_size() / 3;
// we don't know exact weights of the Kusama 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_kusama::max_extrinsic_weight(),
bp_kusama::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 Polkadot -> Kusama messages relay.\n\t\
Polkadot 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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transactions_mortality,
params.target_transactions_mortality,
stall_timeout,
);
let standalone_metrics = params
.standalone_metrics
.map(Ok)
.unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?;
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Polkadot::AVERAGE_BLOCK_INTERVAL,
target_tick: Kusama::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_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target:
bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relay_strategy: params.relay_strategy,
},
},
PolkadotSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
params.target_to_source_headers_relay,
),
KusamaTargetClient::new(
target_client,
lane,
lane_id,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Create standalone metrics for the Polkadot -> Kusama messages loop.
pub(crate) fn standalone_metrics(
source_client: Client<Polkadot>,
target_client: Client<Kusama>,
) -> anyhow::Result<StandaloneMessagesMetrics<Polkadot, Kusama>> {
substrate_relay_helper::messages_lane::standalone_metrics(
source_client,
target_client,
Some(crate::chains::polkadot::TOKEN_ID),
Some(crate::chains::kusama::TOKEN_ID),
Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()),
Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()),
)
} }
/// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage. /// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage.
@@ -26,24 +26,11 @@ use crate::cli::{
use anyhow::anyhow; use anyhow::anyhow;
use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_message_dispatch::{CallOrigin, MessagePayload};
use codec::Decode; use codec::Decode;
use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use frame_support::weights::{DispatchInfo, GetDispatchInfo};
use relay_rialto_client::Rialto; use relay_rialto_client::Rialto;
use sp_core::storage::StorageKey;
use sp_runtime::FixedU128;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we
// want to test our code that is intended to work with real-value chains. So to keep it close to
// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer).
/// The identifier of token, which value is associated with Rialto token value by relayer.
pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::polkadot::TOKEN_ID;
impl CliEncodeCall for Rialto { impl CliEncodeCall for Rialto {
fn max_extrinsic_size() -> u32 {
bp_rialto::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Raw { data } => Decode::decode(&mut &*data.0)?, Call::Raw { data } => Decode::decode(&mut &*data.0)?,
@@ -96,10 +83,6 @@ impl CliChain for Rialto {
rialto_runtime::SS58Prefix::get() as u16 rialto_runtime::SS58Prefix::get() as u16
} }
fn max_extrinsic_weight() -> Weight {
bp_rialto::max_extrinsic_weight()
}
fn encode_message( fn encode_message(
message: encode_message::MessagePayload, message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
@@ -131,11 +114,3 @@ impl CliChain for Rialto {
} }
} }
} }
/// Storage key and initial value of Millau -> Rialto conversion rate.
pub(crate) fn millau_to_rialto_conversion_rate_params() -> (StorageKey, FixedU128) {
(
StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()),
rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE,
)
}
@@ -16,278 +16,46 @@
//! Rialto-to-Millau messages sync entrypoint. //! Rialto-to-Millau messages sync entrypoint.
use std::ops::RangeInclusive;
use codec::Encode; use codec::Encode;
use frame_support::dispatch::GetDispatchInfo;
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_messages::MessageNonce; use messages_relay::relay_strategy::MixStrategy;
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use relay_millau_client::Millau;
use frame_support::weights::Weight; use relay_rialto_client::Rialto;
use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction};
use relay_millau_client::{ use substrate_relay_helper::messages_lane::{
HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder,
}; SubstrateMessageLane,
use relay_rialto_client::{
HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams,
};
use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
use substrate_relay_helper::{
messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics,
SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
},
messages_source::SubstrateMessagesSource,
messages_target::SubstrateMessagesTarget,
STALL_TIMEOUT,
}; };
/// Rialto-to-Millau message lane. /// Description of Rialto -> Millau messages bridge.
pub type MessageLaneRialtoMessagesToMillau = #[derive(Clone, Debug)]
SubstrateMessageLaneToSubstrate<Rialto, RialtoSigningParams, Millau, MillauSigningParams>; pub struct RialtoMessagesToMillau;
#[derive(Clone)]
pub struct RialtoMessagesToMillau {
message_lane: MessageLaneRialtoMessagesToMillau,
}
impl SubstrateMessageLane for RialtoMessagesToMillau { impl SubstrateMessageLane for RialtoMessagesToMillau {
type MessageLane = MessageLaneRialtoMessagesToMillau; const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME);
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> =
bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME);
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD;
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD;
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD;
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str =
bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str =
bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME;
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight =
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
type SourceChain = Rialto; type SourceChain = Rialto;
type TargetChain = Millau; type TargetChain = Millau;
fn source_transactions_author(&self) -> bp_rialto::AccountId { type SourceTransactionSignScheme = Rialto;
(*self.message_lane.source_sign.public().as_array_ref()).into() type TargetTransactionSignScheme = Millau;
}
fn make_messages_receiving_proof_transaction( type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder<
&self, Self,
best_block_id: RialtoHeaderId, millau_runtime::Runtime,
transaction_nonce: IndexOf<Rialto>, millau_runtime::WithRialtoMessagesInstance,
_generated_at_block: MillauHeaderId, >;
proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof, type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder<
) -> Bytes { Self,
let (relayers_state, proof) = proof; rialto_runtime::Runtime,
let call: rialto_runtime::Call = rialto_runtime::WithMillauMessagesInstance,
rialto_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } >;
.into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.message_lane.source_client.genesis_hash();
let transaction = Rialto::sign_transaction(
genesis_hash,
&self.message_lane.source_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.source_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_rialto::max_extrinsic_weight(),
transaction.encode().len(),
bp_rialto::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
fn target_transactions_author(&self) -> bp_millau::AccountId { type RelayStrategy = MixStrategy;
(*self.message_lane.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
best_block_id: MillauHeaderId,
transaction_nonce: IndexOf<Millau>,
_generated_at_header: RialtoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane 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: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof {
relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(),
proof,
messages_count: messages_count as _,
dispatch_weight,
}
.into();
let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Millau::sign_transaction(
genesis_hash,
&self.message_lane.target_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.target_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
log::trace!(
target: "bridge",
"Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}",
call_weight,
bp_millau::max_extrinsic_weight(),
transaction.encode().len(),
bp_millau::max_extrinsic_size(),
);
Bytes(transaction.encode())
}
}
/// Rialto node as messages source.
type RialtoSourceClient = SubstrateMessagesSource<RialtoMessagesToMillau>;
/// Millau node as messages target.
type MillauTargetClient = SubstrateMessagesTarget<RialtoMessagesToMillau>;
/// Run Rialto-to-Millau messages sync.
pub async fn run(
params: MessagesRelayParams<
Rialto,
RialtoSigningParams,
Millau,
MillauSigningParams,
MixStrategy,
>,
) -> anyhow::Result<()> {
let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
params.source_transactions_mortality,
params.target_transactions_mortality,
Rialto::AVERAGE_BLOCK_INTERVAL,
Millau::AVERAGE_BLOCK_INTERVAL,
STALL_TIMEOUT,
);
let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into();
let lane_id = params.lane_id;
let source_client = params.source_client;
let target_client = params.target_client;
let lane = RialtoMessagesToMillau {
message_lane: SubstrateMessageLaneToSubstrate {
source_client: source_client.clone(),
source_sign: params.source_sign,
source_transactions_mortality: params.source_transactions_mortality,
target_client: target_client.clone(),
target_sign: params.target_sign,
target_transactions_mortality: params.target_transactions_mortality,
relayer_id_at_source: relayer_id_at_rialto,
},
};
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3;
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_millau::max_extrinsic_weight(),
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
);
log::info!(
target: "bridge",
"Starting Rialto -> Millau messages relay.\n\t\
Rialto 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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transactions_mortality,
params.target_transactions_mortality,
stall_timeout,
);
let standalone_metrics = params
.standalone_metrics
.map(Ok)
.unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?;
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: lane_id,
source_tick: Rialto::AVERAGE_BLOCK_INTERVAL,
target_tick: Millau::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_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
max_unconfirmed_nonces_at_target:
bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relay_strategy: params.relay_strategy,
},
},
RialtoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
params.target_to_source_headers_relay,
),
MillauTargetClient::new(
target_client,
lane,
lane_id,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Create standalone metrics for the Rialto -> Millau messages loop.
pub(crate) fn standalone_metrics(
source_client: Client<Rialto>,
target_client: Client<Millau>,
) -> anyhow::Result<StandaloneMessagesMetrics<Rialto, Millau>> {
substrate_relay_helper::messages_lane::standalone_metrics(
source_client,
target_client,
Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID),
Some(crate::chains::millau::ASSOCIATED_TOKEN_ID),
Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()),
Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()),
)
} }
/// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage. /// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage.
@@ -22,15 +22,11 @@ use crate::cli::{
}; };
use bp_message_dispatch::MessagePayload; use bp_message_dispatch::MessagePayload;
use codec::Decode; use codec::Decode;
use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use frame_support::weights::{DispatchInfo, GetDispatchInfo};
use relay_rialto_parachain_client::RialtoParachain; use relay_rialto_parachain_client::RialtoParachain;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
impl CliEncodeCall for RialtoParachain { impl CliEncodeCall for RialtoParachain {
fn max_extrinsic_size() -> u32 {
bp_rialto_parachain::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Raw { data } => Decode::decode(&mut &*data.0)?, Call::Raw { data } => Decode::decode(&mut &*data.0)?,
@@ -71,10 +67,6 @@ impl CliChain for RialtoParachain {
rialto_parachain_runtime::SS58Prefix::get() as u16 rialto_parachain_runtime::SS58Prefix::get() as u16
} }
fn max_extrinsic_weight() -> Weight {
bp_rialto_parachain::max_extrinsic_weight()
}
fn encode_message( fn encode_message(
_message: encode_message::MessagePayload, _message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
@@ -33,10 +33,6 @@ use crate::cli::{
pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000;
impl CliEncodeCall for Rococo { impl CliEncodeCall for Rococo {
fn max_extrinsic_size() -> u32 {
bp_rococo::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System(
@@ -48,8 +44,8 @@ impl CliEncodeCall for Rococo {
match *bridge_instance_index { match *bridge_instance_index {
bridge::ROCOCO_TO_WOCOCO_INDEX => { bridge::ROCOCO_TO_WOCOCO_INDEX => {
let payload = Decode::decode(&mut &*payload.0)?; let payload = Decode::decode(&mut &*payload.0)?;
relay_rococo_client::runtime::Call::BridgeMessagesWococo( relay_rococo_client::runtime::Call::BridgeWococoMessages(
relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message( relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message(
lane.0, payload, fee.0, lane.0, payload, fee.0,
), ),
) )
@@ -89,10 +85,6 @@ impl CliChain for Rococo {
42 42
} }
fn max_extrinsic_weight() -> Weight {
bp_wococo::max_extrinsic_weight()
}
fn encode_message( fn encode_message(
_message: encode_message::MessagePayload, _message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
@@ -19,7 +19,7 @@
use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY;
use sp_core::Pair; use sp_core::Pair;
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams};
/// Description of Rococo -> Wococo finalized headers bridge. /// Description of Rococo -> Wococo finalized headers bridge.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -48,7 +48,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
); );
relay_substrate_client::guard::abort_when_account_balance_decreased( relay_substrate_client::guard::abort_when_account_balance_decreased(
target_client.clone(), target_client.clone(),
transaction_params.transactions_signer.public().into(), transaction_params.signer.public().into(),
MAXIMAL_BALANCE_DECREASE_PER_DAY, MAXIMAL_BALANCE_DECREASE_PER_DAY,
); );
} }
@@ -16,280 +16,41 @@
//! Rococo-to-Wococo messages sync entrypoint. //! Rococo-to-Wococo messages sync entrypoint.
use std::ops::RangeInclusive;
use codec::Encode;
use sp_core::{Bytes, Pair};
use bp_messages::MessageNonce;
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use frame_support::weights::Weight; use frame_support::weights::Weight;
use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use messages_relay::relay_strategy::MixStrategy;
use relay_rococo_client::{ use relay_rococo_client::Rococo;
HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, use relay_wococo_client::Wococo;
}; use substrate_relay_helper::messages_lane::SubstrateMessageLane;
use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
use relay_wococo_client::{
HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo,
};
use substrate_relay_helper::{
messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics,
SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
},
messages_source::SubstrateMessagesSource,
messages_target::SubstrateMessagesTarget,
STALL_TIMEOUT,
};
/// Rococo-to-Wococo message lane. /// Description of Rococo -> Wococo messages bridge.
pub type MessageLaneRococoMessagesToWococo = #[derive(Clone, Debug)]
SubstrateMessageLaneToSubstrate<Rococo, RococoSigningParams, Wococo, WococoSigningParams>; pub struct RococoMessagesToWococo;
substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!(
#[derive(Clone)] RococoMessagesToWococo,
pub struct RococoMessagesToWococo { RococoMessagesToWococoReceiveMessagesProofCallBuilder,
message_lane: MessageLaneRococoMessagesToWococo, relay_wococo_client::runtime::Call::BridgeRococoMessages,
} relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof
);
substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!(
RococoMessagesToWococo,
RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder,
relay_rococo_client::runtime::Call::BridgeWococoMessages,
relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof
);
impl SubstrateMessageLane for RococoMessagesToWococo { impl SubstrateMessageLane for RococoMessagesToWococo {
type MessageLane = MessageLaneRococoMessagesToWococo; const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None;
const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None;
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;
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME;
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight =
bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
type SourceChain = Rococo; type SourceChain = Rococo;
type TargetChain = Wococo; type TargetChain = Wococo;
fn source_transactions_author(&self) -> bp_rococo::AccountId { type SourceTransactionSignScheme = Rococo;
(*self.message_lane.source_sign.public().as_array_ref()).into() type TargetTransactionSignScheme = Wococo;
}
fn make_messages_receiving_proof_transaction( type ReceiveMessagesProofCallBuilder = RococoMessagesToWococoReceiveMessagesProofCallBuilder;
&self, type ReceiveMessagesDeliveryProofCallBuilder =
best_block_id: RococoHeaderId, RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder;
transaction_nonce: IndexOf<Rococo>,
_generated_at_block: WococoHeaderId,
proof: <Self::MessageLane 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.message_lane.source_client.genesis_hash();
let transaction = Rococo::sign_transaction(
genesis_hash,
&self.message_lane.source_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.source_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
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 { type RelayStrategy = MixStrategy;
(*self.message_lane.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
best_block_id: WococoHeaderId,
transaction_nonce: IndexOf<Wococo>,
_generated_at_header: RococoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane 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.message_lane.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Wococo::sign_transaction(
genesis_hash,
&self.message_lane.target_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.target_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
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<RococoMessagesToWococo>;
/// Wococo node as messages target.
type WococoTargetClient = SubstrateMessagesTarget<RococoMessagesToWococo>;
/// Run Rococo-to-Wococo messages sync.
pub async fn run(
params: MessagesRelayParams<
Rococo,
RococoSigningParams,
Wococo,
WococoSigningParams,
MixStrategy,
>,
) -> anyhow::Result<()> {
let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
params.source_transactions_mortality,
params.target_transactions_mortality,
Rococo::AVERAGE_BLOCK_INTERVAL,
Wococo::AVERAGE_BLOCK_INTERVAL,
STALL_TIMEOUT,
);
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 target_client = params.target_client;
let lane = RococoMessagesToWococo {
message_lane: SubstrateMessageLaneToSubstrate {
source_client: source_client.clone(),
source_sign: params.source_sign,
source_transactions_mortality: params.source_transactions_mortality,
target_client: target_client.clone(),
target_sign: params.target_sign,
target_transactions_mortality: params.target_transactions_mortality,
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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transactions_mortality,
params.target_transactions_mortality,
stall_timeout,
);
let standalone_metrics = params
.standalone_metrics
.map(Ok)
.unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?;
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,
relay_strategy: params.relay_strategy,
},
},
RococoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
params.target_to_source_headers_relay,
),
WococoTargetClient::new(
target_client,
lane,
lane_id,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Create standalone metrics for the Rococo -> Wococo messages loop.
pub(crate) fn standalone_metrics(
source_client: Client<Rococo>,
target_client: Client<Wococo>,
) -> anyhow::Result<StandaloneMessagesMetrics<Rococo, Wococo>> {
substrate_relay_helper::messages_lane::standalone_metrics(
source_client,
target_client,
None,
None,
None,
None,
)
} }
@@ -18,7 +18,6 @@
use crate::cli::{encode_message, CliChain}; use crate::cli::{encode_message, CliChain};
use anyhow::anyhow; use anyhow::anyhow;
use frame_support::weights::Weight;
use relay_westend_client::Westend; use relay_westend_client::Westend;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
@@ -32,10 +31,6 @@ impl CliChain for Westend {
42 42
} }
fn max_extrinsic_weight() -> Weight {
0
}
fn encode_message( fn encode_message(
_message: encode_message::MessagePayload, _message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
@@ -16,7 +16,7 @@
use anyhow::anyhow; use anyhow::anyhow;
use codec::Decode; use codec::Decode;
use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use frame_support::weights::{DispatchClass, DispatchInfo, Pays};
use relay_wococo_client::Wococo; use relay_wococo_client::Wococo;
use sp_version::RuntimeVersion; use sp_version::RuntimeVersion;
@@ -27,10 +27,6 @@ use crate::cli::{
}; };
impl CliEncodeCall for Wococo { impl CliEncodeCall for Wococo {
fn max_extrinsic_size() -> u32 {
bp_wococo::max_extrinsic_size()
}
fn encode_call(call: &Call) -> anyhow::Result<Self::Call> { fn encode_call(call: &Call) -> anyhow::Result<Self::Call> {
Ok(match call { Ok(match call {
Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System(
@@ -42,8 +38,8 @@ impl CliEncodeCall for Wococo {
match *bridge_instance_index { match *bridge_instance_index {
bridge::WOCOCO_TO_ROCOCO_INDEX => { bridge::WOCOCO_TO_ROCOCO_INDEX => {
let payload = Decode::decode(&mut &*payload.0)?; let payload = Decode::decode(&mut &*payload.0)?;
relay_wococo_client::runtime::Call::BridgeMessagesRococo( relay_wococo_client::runtime::Call::BridgeRococoMessages(
relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message( relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message(
lane.0, payload, fee.0, lane.0, payload, fee.0,
), ),
) )
@@ -83,10 +79,6 @@ impl CliChain for Wococo {
42 42
} }
fn max_extrinsic_weight() -> Weight {
bp_wococo::max_extrinsic_weight()
}
fn encode_message( fn encode_message(
_message: encode_message::MessagePayload, _message: encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload> { ) -> anyhow::Result<Self::MessagePayload> {
@@ -17,7 +17,7 @@
//! Wococo-to-Rococo headers sync entrypoint. //! Wococo-to-Rococo headers sync entrypoint.
use sp_core::Pair; use sp_core::Pair;
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams};
/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat
/// relay as gone wild. /// relay as gone wild.
@@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
); );
relay_substrate_client::guard::abort_when_account_balance_decreased( relay_substrate_client::guard::abort_when_account_balance_decreased(
target_client.clone(), target_client.clone(),
transaction_params.transactions_signer.public().into(), transaction_params.signer.public().into(),
MAXIMAL_BALANCE_DECREASE_PER_DAY, MAXIMAL_BALANCE_DECREASE_PER_DAY,
); );
} }
@@ -16,279 +16,42 @@
//! Wococo-to-Rococo messages sync entrypoint. //! Wococo-to-Rococo messages sync entrypoint.
use std::ops::RangeInclusive;
use codec::Encode;
use sp_core::{Bytes, Pair};
use bp_messages::MessageNonce;
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use frame_support::weights::Weight; use frame_support::weights::Weight;
use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy};
use relay_rococo_client::{
HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams,
};
use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
use relay_wococo_client::{
HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo,
};
use substrate_relay_helper::{
messages_lane::{
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics,
SubstrateMessageLane, SubstrateMessageLaneToSubstrate,
},
messages_source::SubstrateMessagesSource,
messages_target::SubstrateMessagesTarget,
STALL_TIMEOUT,
};
/// Wococo-to-Rococo message lane. use messages_relay::relay_strategy::MixStrategy;
pub type MessageLaneWococoMessagesToRococo = use relay_rococo_client::Rococo;
SubstrateMessageLaneToSubstrate<Wococo, WococoSigningParams, Rococo, RococoSigningParams>; use relay_wococo_client::Wococo;
use substrate_relay_helper::messages_lane::SubstrateMessageLane;
#[derive(Clone)] /// Description of Wococo -> Rococo messages bridge.
pub struct WococoMessagesToRococo { #[derive(Clone, Debug)]
message_lane: MessageLaneWococoMessagesToRococo, pub struct WococoMessagesToRococo;
} substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!(
WococoMessagesToRococo,
WococoMessagesToRococoReceiveMessagesProofCallBuilder,
relay_rococo_client::runtime::Call::BridgeWococoMessages,
relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof
);
substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!(
WococoMessagesToRococo,
WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder,
relay_wococo_client::runtime::Call::BridgeRococoMessages,
relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof
);
impl SubstrateMessageLane for WococoMessagesToRococo { impl SubstrateMessageLane for WococoMessagesToRococo {
type MessageLane = MessageLaneWococoMessagesToRococo; const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None;
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None;
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;
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME;
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight =
bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
type SourceChain = Wococo; type SourceChain = Wococo;
type TargetChain = Rococo; type TargetChain = Rococo;
fn source_transactions_author(&self) -> bp_wococo::AccountId { type SourceTransactionSignScheme = Wococo;
(*self.message_lane.source_sign.public().as_array_ref()).into() type TargetTransactionSignScheme = Rococo;
}
fn make_messages_receiving_proof_transaction( type ReceiveMessagesProofCallBuilder = WococoMessagesToRococoReceiveMessagesProofCallBuilder;
&self, type ReceiveMessagesDeliveryProofCallBuilder =
best_block_id: WococoHeaderId, WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder;
transaction_nonce: IndexOf<Wococo>,
_generated_at_block: RococoHeaderId,
proof: <Self::MessageLane 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.message_lane.source_client.genesis_hash();
let transaction = Wococo::sign_transaction(
genesis_hash,
&self.message_lane.source_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.source_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
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 { type RelayStrategy = MixStrategy;
(*self.message_lane.target_sign.public().as_array_ref()).into()
}
fn make_messages_delivery_transaction(
&self,
best_block_id: WococoHeaderId,
transaction_nonce: IndexOf<Rococo>,
_generated_at_header: WococoHeaderId,
_nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane 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.message_lane.relayer_id_at_source.clone(),
proof,
messages_count as _,
dispatch_weight,
),
);
let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Rococo::sign_transaction(
genesis_hash,
&self.message_lane.target_sign,
relay_substrate_client::TransactionEra::new(
best_block_id,
self.message_lane.target_transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce),
);
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<WococoMessagesToRococo>;
/// Rococo node as messages target.
type RococoTargetClient = SubstrateMessagesTarget<WococoMessagesToRococo>;
/// Run Wococo-to-Rococo messages sync.
pub async fn run(
params: MessagesRelayParams<
Wococo,
WococoSigningParams,
Rococo,
RococoSigningParams,
MixStrategy,
>,
) -> anyhow::Result<()> {
let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
params.source_transactions_mortality,
params.target_transactions_mortality,
Wococo::AVERAGE_BLOCK_INTERVAL,
Rococo::AVERAGE_BLOCK_INTERVAL,
STALL_TIMEOUT,
);
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 target_client = params.target_client;
let lane = WococoMessagesToRococo {
message_lane: SubstrateMessageLaneToSubstrate {
source_client: source_client.clone(),
source_sign: params.source_sign,
source_transactions_mortality: params.source_transactions_mortality,
target_client: target_client.clone(),
target_sign: params.target_sign,
target_transactions_mortality: params.target_transactions_mortality,
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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transactions_mortality,
params.target_transactions_mortality,
stall_timeout,
);
let standalone_metrics = params
.standalone_metrics
.map(Ok)
.unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?;
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,
relay_strategy: params.relay_strategy,
},
},
WococoSourceClient::new(
source_client.clone(),
lane.clone(),
lane_id,
params.target_to_source_headers_relay,
),
RococoTargetClient::new(
target_client,
lane,
lane_id,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Create standalone metrics for the Wococo -> Rococo messages loop.
pub(crate) fn standalone_metrics(
source_client: Client<Wococo>,
target_client: Client<Rococo>,
) -> anyhow::Result<StandaloneMessagesMetrics<Wococo, Rococo>> {
substrate_relay_helper::messages_lane::standalone_metrics(
source_client,
target_client,
None,
None,
None,
None,
)
} }
@@ -68,7 +68,7 @@ macro_rules! select_full_bridge {
// Relay-messages // Relay-messages
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::chains::millau_messages_to_rialto::run as relay_messages; use crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane;
// Send-message / Estimate-fee // Send-message / Estimate-fee
#[allow(unused_imports)] #[allow(unused_imports)]
@@ -90,7 +90,7 @@ macro_rules! select_full_bridge {
// Relay-messages // Relay-messages
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::chains::rialto_messages_to_millau::run as relay_messages; use crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane;
// Send-message / Estimate-fee // Send-message / Estimate-fee
#[allow(unused_imports)] #[allow(unused_imports)]
@@ -113,7 +113,7 @@ macro_rules! select_full_bridge {
// Relay-messages // Relay-messages
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::chains::rococo_messages_to_wococo::run as relay_messages; use crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane;
// Send-message / Estimate-fee // Send-message / Estimate-fee
#[allow(unused_imports)] #[allow(unused_imports)]
@@ -135,7 +135,7 @@ macro_rules! select_full_bridge {
// Relay-messages // Relay-messages
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::chains::wococo_messages_to_rococo::run as relay_messages; use crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane;
// Send-message / Estimate-fee // Send-message / Estimate-fee
#[allow(unused_imports)] #[allow(unused_imports)]
@@ -157,7 +157,7 @@ macro_rules! select_full_bridge {
// Relay-messages // Relay-messages
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::chains::kusama_messages_to_polkadot::run as relay_messages; use crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane;
// Send-message / Estimate-fee // Send-message / Estimate-fee
#[allow(unused_imports)] #[allow(unused_imports)]
@@ -179,7 +179,7 @@ macro_rules! select_full_bridge {
// Relay-messages // Relay-messages
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::chains::polkadot_messages_to_kusama::run as relay_messages; use crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane;
// Send-message / Estimate-fee // Send-message / Estimate-fee
#[allow(unused_imports)] #[allow(unused_imports)]
@@ -84,9 +84,6 @@ pub enum Call {
} }
pub trait CliEncodeCall: Chain { pub trait CliEncodeCall: Chain {
/// Maximal size (in bytes) of any extrinsic (from the runtime).
fn max_extrinsic_size() -> u32;
/// Encode a CLI call. /// Encode a CLI call.
fn encode_call(call: &Call) -> anyhow::Result<Self::Call>; fn encode_call(call: &Call) -> anyhow::Result<Self::Call>;
@@ -20,7 +20,6 @@ use std::convert::TryInto;
use bp_messages::LaneId; use bp_messages::LaneId;
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::weights::Weight;
use sp_runtime::app_crypto::Ss58Codec; use sp_runtime::app_crypto::Ss58Codec;
use structopt::{clap::arg_enum, StructOpt}; use structopt::{clap::arg_enum, StructOpt};
@@ -258,9 +257,6 @@ pub trait CliChain: relay_substrate_client::Chain {
fn encode_message( fn encode_message(
message: crate::cli::encode_message::MessagePayload, message: crate::cli::encode_message::MessagePayload,
) -> anyhow::Result<Self::MessagePayload>; ) -> anyhow::Result<Self::MessagePayload>;
/// Maximal extrinsic weight (from the runtime).
fn max_extrinsic_weight() -> Weight;
} }
/// Lane id. /// Lane id.
@@ -125,11 +125,10 @@ impl RelayHeaders {
let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into();
GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?;
let target_transactions_params = let target_transactions_params = substrate_relay_helper::TransactionParams {
substrate_relay_helper::finality_pipeline::TransactionParams { signer: target_sign,
transactions_signer: target_sign, mortality: target_transactions_mortality,
transactions_mortality: target_transactions_mortality, };
};
Finality::start_relay_guards(&target_client, &target_transactions_params); Finality::start_relay_guards(&target_client, &target_transactions_params);
substrate_relay_helper::finality_pipeline::run::<Finality>( substrate_relay_helper::finality_pipeline::run::<Finality>(
@@ -35,7 +35,7 @@ use relay_utils::metrics::MetricsParams;
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use substrate_relay_helper::{ use substrate_relay_helper::{
finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams,
on_demand_headers::OnDemandHeadersRelay, on_demand_headers::OnDemandHeadersRelay, TransactionParams,
}; };
use crate::{ use crate::{
@@ -139,13 +139,12 @@ macro_rules! select_bridge {
use crate::chains::{ use crate::chains::{
millau_messages_to_rialto::{ millau_messages_to_rialto::{
run as left_to_right_messages,
standalone_metrics as left_to_right_standalone_metrics,
update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate,
MillauMessagesToRialto as LeftToRightMessageLane,
}, },
rialto_messages_to_millau::{ rialto_messages_to_millau::{
run as right_to_left_messages,
update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate,
RialtoMessagesToMillau as RightToLeftMessageLane,
}, },
}; };
@@ -187,11 +186,8 @@ macro_rules! select_bridge {
bp_wococo::SESSION_LENGTH; bp_wococo::SESSION_LENGTH;
use crate::chains::{ use crate::chains::{
rococo_messages_to_wococo::{ rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane,
run as left_to_right_messages, wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane,
standalone_metrics as left_to_right_standalone_metrics,
},
wococo_messages_to_rococo::run as right_to_left_messages,
}; };
async fn update_right_to_left_conversion_rate( async fn update_right_to_left_conversion_rate(
@@ -269,13 +265,12 @@ macro_rules! select_bridge {
use crate::chains::{ use crate::chains::{
kusama_messages_to_polkadot::{ kusama_messages_to_polkadot::{
run as left_to_right_messages,
standalone_metrics as left_to_right_standalone_metrics,
update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate,
KusamaMessagesToPolkadot as LeftToRightMessageLane,
}, },
polkadot_messages_to_kusama::{ polkadot_messages_to_kusama::{
run as right_to_left_messages,
update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate,
PolkadotMessagesToKusama as RightToLeftMessageLane,
}, },
}; };
@@ -358,7 +353,9 @@ impl RelayHeadersAndMessages {
let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params: MetricsParams = params.shared.prometheus_params.into();
let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); let metrics_params = relay_utils::relay_metrics(metrics_params).into_params();
let left_to_right_metrics = let left_to_right_metrics =
left_to_right_standalone_metrics(left_client.clone(), right_client.clone())?; substrate_relay_helper::messages_metrics::standalone_metrics::<
LeftToRightMessageLane,
>(left_client.clone(), right_client.clone())?;
let right_to_left_metrics = left_to_right_metrics.clone().reverse(); let right_to_left_metrics = left_to_right_metrics.clone().reverse();
// start conversion rate update loops for left/right chains // start conversion rate update loops for left/right chains
@@ -489,16 +486,14 @@ impl RelayHeadersAndMessages {
} }
// start on-demand header relays // start on-demand header relays
let left_to_right_transaction_params = let left_to_right_transaction_params = TransactionParams {
substrate_relay_helper::finality_pipeline::TransactionParams { mortality: right_transactions_mortality,
transactions_mortality: right_transactions_mortality, signer: right_sign.clone(),
transactions_signer: right_sign.clone(), };
}; let right_to_left_transaction_params = TransactionParams {
let right_to_left_transaction_params = mortality: left_transactions_mortality,
substrate_relay_helper::finality_pipeline::TransactionParams { signer: left_sign.clone(),
transactions_mortality: left_transactions_mortality, };
transactions_signer: left_sign.clone(),
};
LeftToRightFinality::start_relay_guards( LeftToRightFinality::start_relay_guards(
&right_client, &right_client,
&left_to_right_transaction_params, &left_to_right_transaction_params,
@@ -526,13 +521,19 @@ impl RelayHeadersAndMessages {
let mut message_relays = Vec::with_capacity(lanes.len() * 2); let mut message_relays = Vec::with_capacity(lanes.len() * 2);
for lane in lanes { for lane in lanes {
let lane = lane.into(); let lane = lane.into();
let left_to_right_messages = left_to_right_messages(MessagesRelayParams { let left_to_right_messages = substrate_relay_helper::messages_lane::run::<
LeftToRightMessageLane,
>(MessagesRelayParams {
source_client: left_client.clone(), source_client: left_client.clone(),
source_sign: left_sign.clone(), source_transaction_params: TransactionParams {
source_transactions_mortality: left_transactions_mortality, signer: left_sign.clone(),
mortality: left_transactions_mortality,
},
target_client: right_client.clone(), target_client: right_client.clone(),
target_sign: right_sign.clone(), target_transaction_params: TransactionParams {
target_transactions_mortality: right_transactions_mortality, signer: right_sign.clone(),
mortality: right_transactions_mortality,
},
source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()),
target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()),
lane_id: lane, lane_id: lane,
@@ -542,13 +543,19 @@ impl RelayHeadersAndMessages {
}) })
.map_err(|e| anyhow::format_err!("{}", e)) .map_err(|e| anyhow::format_err!("{}", e))
.boxed(); .boxed();
let right_to_left_messages = right_to_left_messages(MessagesRelayParams { let right_to_left_messages = substrate_relay_helper::messages_lane::run::<
RightToLeftMessageLane,
>(MessagesRelayParams {
source_client: right_client.clone(), source_client: right_client.clone(),
source_sign: right_sign.clone(), source_transaction_params: TransactionParams {
source_transactions_mortality: right_transactions_mortality, signer: right_sign.clone(),
mortality: right_transactions_mortality,
},
target_client: left_client.clone(), target_client: left_client.clone(),
target_sign: left_sign.clone(), target_transaction_params: TransactionParams {
target_transactions_mortality: left_transactions_mortality, signer: left_sign.clone(),
mortality: left_transactions_mortality,
},
source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()),
target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()),
lane_id: lane, lane_id: lane,
@@ -18,7 +18,7 @@ use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
use messages_relay::relay_strategy::MixStrategy; use messages_relay::relay_strategy::MixStrategy;
use substrate_relay_helper::messages_lane::MessagesRelayParams; use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams};
use crate::{ use crate::{
cli::{ cli::{
@@ -84,13 +84,17 @@ impl RelayMessages {
let relayer_mode = self.relayer_mode.into(); let relayer_mode = self.relayer_mode.into();
let relay_strategy = MixStrategy::new(relayer_mode); let relay_strategy = MixStrategy::new(relayer_mode);
relay_messages(MessagesRelayParams { substrate_relay_helper::messages_lane::run::<MessagesLane>(MessagesRelayParams {
source_client, source_client,
source_sign, source_transaction_params: TransactionParams {
source_transactions_mortality, signer: source_sign,
mortality: source_transactions_mortality,
},
target_client, target_client,
target_sign, target_transaction_params: TransactionParams {
target_transactions_mortality, signer: target_sign,
mortality: target_transactions_mortality,
},
source_to_target_headers_relay: None, source_to_target_headers_relay: None,
target_to_source_headers_relay: None, target_to_source_headers_relay: None,
lane_id: self.lane.into(), lane_id: self.lane.into(),
@@ -22,7 +22,7 @@ use crate::cli::{
SourceSigningParams, TargetSigningParams, SourceSigningParams, TargetSigningParams,
}; };
use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_message_dispatch::{CallOrigin, MessagePayload};
use bp_runtime::BalanceOf; use bp_runtime::{BalanceOf, Chain as _};
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight; use frame_support::weights::Weight;
use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction};
+37 -2
View File
@@ -16,10 +16,12 @@
//! Types used to connect to the Kusama chain. //! Types used to connect to the Kusama chain.
use bp_messages::MessageNonce;
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight;
use relay_substrate_client::{ use relay_substrate_client::{
Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf,
UnsignedTransaction, TransactionSignScheme, UnsignedTransaction,
}; };
use sp_core::{storage::StorageKey, Pair}; use sp_core::{storage::StorageKey, Pair};
use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
@@ -44,10 +46,19 @@ impl ChainBase for Kusama {
type Balance = bp_kusama::Balance; type Balance = bp_kusama::Balance;
type Index = bp_kusama::Nonce; type Index = bp_kusama::Nonce;
type Signature = bp_kusama::Signature; type Signature = bp_kusama::Signature;
fn max_extrinsic_size() -> u32 {
bp_kusama::Kusama::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_kusama::Kusama::max_extrinsic_weight()
}
} }
impl Chain for Kusama { impl Chain for Kusama {
const NAME: &'static str = "Kusama"; const NAME: &'static str = "Kusama";
const TOKEN_ID: Option<&'static str> = Some("kusama");
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -59,6 +70,30 @@ impl Chain for Kusama {
type WeightToFee = bp_kusama::WeightToFee; type WeightToFee = bp_kusama::WeightToFee;
} }
impl ChainWithMessages for Kusama {
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME;
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD;
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD;
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD;
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str =
bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
bp_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
bp_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
type WeightInfo = ();
}
impl ChainWithBalances for Kusama { impl ChainWithBalances for Kusama {
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
StorageKey(bp_kusama::account_info_storage_key(account_id)) StorageKey(bp_kusama::account_info_storage_key(account_id))
+1
View File
@@ -12,6 +12,7 @@ relay-utils = { path = "../utils" }
# Supported Chains # Supported Chains
bp-messages = { path = "../../primitives/messages" }
bp-millau = { path = "../../primitives/chain-millau" } bp-millau = { path = "../../primitives/chain-millau" }
millau-runtime = { path = "../../bin/millau/runtime" } millau-runtime = { path = "../../bin/millau/runtime" }
+37 -1
View File
@@ -16,9 +16,11 @@
//! Types used to connect to the Millau-Substrate chain. //! Types used to connect to the Millau-Substrate chain.
use bp_messages::MessageNonce;
use codec::{Compact, Decode, Encode}; use codec::{Compact, Decode, Encode};
use frame_support::weights::Weight;
use relay_substrate_client::{ use relay_substrate_client::{
BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf,
TransactionSignScheme, UnsignedTransaction, TransactionSignScheme, UnsignedTransaction,
}; };
use sp_core::{storage::StorageKey, Pair}; use sp_core::{storage::StorageKey, Pair};
@@ -42,10 +44,44 @@ impl ChainBase for Millau {
type Balance = millau_runtime::Balance; type Balance = millau_runtime::Balance;
type Index = millau_runtime::Index; type Index = millau_runtime::Index;
type Signature = millau_runtime::Signature; type Signature = millau_runtime::Signature;
fn max_extrinsic_size() -> u32 {
bp_millau::Millau::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_millau::Millau::max_extrinsic_weight()
}
}
impl ChainWithMessages for Millau {
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME;
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD;
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD;
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD;
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str =
bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
type WeightInfo = ();
} }
impl Chain for Millau { impl Chain for Millau {
const NAME: &'static str = "Millau"; const NAME: &'static str = "Millau";
// Rialto token has no value, but we associate it with KSM token
const TOKEN_ID: Option<&'static str> = Some("kusama");
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
+37 -2
View File
@@ -16,10 +16,12 @@
//! Types used to connect to the Polkadot chain. //! Types used to connect to the Polkadot chain.
use bp_messages::MessageNonce;
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight;
use relay_substrate_client::{ use relay_substrate_client::{
Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf,
UnsignedTransaction, TransactionSignScheme, UnsignedTransaction,
}; };
use sp_core::{storage::StorageKey, Pair}; use sp_core::{storage::StorageKey, Pair};
use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
@@ -44,10 +46,19 @@ impl ChainBase for Polkadot {
type Balance = bp_polkadot::Balance; type Balance = bp_polkadot::Balance;
type Index = bp_polkadot::Nonce; type Index = bp_polkadot::Nonce;
type Signature = bp_polkadot::Signature; type Signature = bp_polkadot::Signature;
fn max_extrinsic_size() -> u32 {
bp_polkadot::Polkadot::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_polkadot::Polkadot::max_extrinsic_weight()
}
} }
impl Chain for Polkadot { impl Chain for Polkadot {
const NAME: &'static str = "Polkadot"; const NAME: &'static str = "Polkadot";
const TOKEN_ID: Option<&'static str> = Some("polkadot");
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -59,6 +70,30 @@ impl Chain for Polkadot {
type WeightToFee = bp_polkadot::WeightToFee; type WeightToFee = bp_polkadot::WeightToFee;
} }
impl ChainWithMessages for Polkadot {
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME;
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD;
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD;
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD;
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str =
bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
bp_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
bp_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
type WeightInfo = ();
}
impl ChainWithBalances for Polkadot { impl ChainWithBalances for Polkadot {
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
StorageKey(bp_polkadot::account_info_storage_key(account_id)) StorageKey(bp_polkadot::account_info_storage_key(account_id))
@@ -16,6 +16,7 @@
//! Types used to connect to the Rialto-Substrate chain. //! Types used to connect to the Rialto-Substrate chain.
use frame_support::weights::Weight;
use relay_substrate_client::{Chain, ChainBase}; use relay_substrate_client::{Chain, ChainBase};
use std::time::Duration; use std::time::Duration;
@@ -37,10 +38,19 @@ impl ChainBase for RialtoParachain {
type Balance = rialto_parachain_runtime::Balance; type Balance = rialto_parachain_runtime::Balance;
type Index = rialto_parachain_runtime::Index; type Index = rialto_parachain_runtime::Index;
type Signature = rialto_parachain_runtime::Signature; type Signature = rialto_parachain_runtime::Signature;
fn max_extrinsic_size() -> u32 {
bp_rialto::Rialto::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_rialto::Rialto::max_extrinsic_weight()
}
} }
impl Chain for RialtoParachain { impl Chain for RialtoParachain {
const NAME: &'static str = "RialtoParachain"; const NAME: &'static str = "RialtoParachain";
const TOKEN_ID: Option<&'static str> = None;
// should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "<UNIMPLEMENTED>"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "<UNIMPLEMENTED>";
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
+1
View File
@@ -12,6 +12,7 @@ relay-utils = { path = "../utils" }
# Bridge dependencies # Bridge dependencies
bp-messages = { path = "../../primitives/messages" }
bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto = { path = "../../primitives/chain-rialto" }
rialto-runtime = { path = "../../bin/rialto/runtime" } rialto-runtime = { path = "../../bin/rialto/runtime" }
+37 -1
View File
@@ -16,9 +16,11 @@
//! Types used to connect to the Rialto-Substrate chain. //! Types used to connect to the Rialto-Substrate chain.
use bp_messages::MessageNonce;
use codec::{Compact, Decode, Encode}; use codec::{Compact, Decode, Encode};
use frame_support::weights::Weight;
use relay_substrate_client::{ use relay_substrate_client::{
BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf,
TransactionSignScheme, UnsignedTransaction, TransactionSignScheme, UnsignedTransaction,
}; };
use sp_core::{storage::StorageKey, Pair}; use sp_core::{storage::StorageKey, Pair};
@@ -42,10 +44,20 @@ impl ChainBase for Rialto {
type Balance = rialto_runtime::Balance; type Balance = rialto_runtime::Balance;
type Index = rialto_runtime::Index; type Index = rialto_runtime::Index;
type Signature = rialto_runtime::Signature; type Signature = rialto_runtime::Signature;
fn max_extrinsic_size() -> u32 {
bp_rialto::Rialto::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_rialto::Rialto::max_extrinsic_weight()
}
} }
impl Chain for Rialto { impl Chain for Rialto {
const NAME: &'static str = "Rialto"; const NAME: &'static str = "Rialto";
// Rialto token has no value, but we associate it with DOT token
const TOKEN_ID: Option<&'static str> = Some("polkadot");
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
@@ -57,6 +69,30 @@ impl Chain for Rialto {
type WeightToFee = bp_rialto::WeightToFee; type WeightToFee = bp_rialto::WeightToFee;
} }
impl ChainWithMessages for Rialto {
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME;
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD;
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD;
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD;
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str =
bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
type WeightInfo = ();
}
impl ChainWithBalances for Rialto { impl ChainWithBalances for Rialto {
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
use frame_support::storage::generator::StorageMap; use frame_support::storage::generator::StorageMap;
+37 -2
View File
@@ -16,10 +16,12 @@
//! Types used to connect to the Rococo-Substrate chain. //! Types used to connect to the Rococo-Substrate chain.
use bp_messages::MessageNonce;
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight;
use relay_substrate_client::{ use relay_substrate_client::{
Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf,
UnsignedTransaction, TransactionSignScheme, UnsignedTransaction,
}; };
use sp_core::{storage::StorageKey, Pair}; use sp_core::{storage::StorageKey, Pair};
use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
@@ -47,10 +49,19 @@ impl ChainBase for Rococo {
type Balance = bp_rococo::Balance; type Balance = bp_rococo::Balance;
type Index = bp_rococo::Nonce; type Index = bp_rococo::Nonce;
type Signature = bp_rococo::Signature; type Signature = bp_rococo::Signature;
fn max_extrinsic_size() -> u32 {
bp_rococo::Rococo::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_rococo::Rococo::max_extrinsic_weight()
}
} }
impl Chain for Rococo { impl Chain for Rococo {
const NAME: &'static str = "Rococo"; const NAME: &'static str = "Rococo";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -62,6 +73,30 @@ impl Chain for Rococo {
type WeightToFee = bp_rococo::WeightToFee; type WeightToFee = bp_rococo::WeightToFee;
} }
impl ChainWithMessages for Rococo {
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME;
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD;
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD;
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD;
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str =
bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
type WeightInfo = ();
}
impl ChainWithBalances for Rococo { impl ChainWithBalances for Rococo {
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
StorageKey(bp_rococo::account_info_storage_key(account_id)) StorageKey(bp_rococo::account_info_storage_key(account_id))
+2 -2
View File
@@ -74,7 +74,7 @@ pub enum Call {
BridgeGrandpaWococo(BridgeGrandpaWococoCall), BridgeGrandpaWococo(BridgeGrandpaWococoCall),
/// Wococo messages pallet. /// Wococo messages pallet.
#[codec(index = 44)] #[codec(index = 44)]
BridgeMessagesWococo(BridgeMessagesWococoCall), BridgeWococoMessages(BridgeWococoMessagesCall),
} }
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
@@ -105,7 +105,7 @@ pub enum BridgeGrandpaWococoCall {
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub enum BridgeMessagesWococoCall { pub enum BridgeWococoMessagesCall {
#[codec(index = 3)] #[codec(index = 3)]
send_message( send_message(
LaneId, LaneId,
@@ -20,7 +20,9 @@ thiserror = "1.0.26"
# Bridge dependencies # Bridge dependencies
bp-header-chain = { path = "../../primitives/header-chain" } bp-header-chain = { path = "../../primitives/header-chain" }
bp-messages = { path = "../../primitives/messages" }
bp-runtime = { path = "../../primitives/runtime" } bp-runtime = { path = "../../primitives/runtime" }
pallet-bridge-messages = { path = "../../modules/messages" }
finality-relay = { path = "../finality" } finality-relay = { path = "../finality" }
relay-utils = { path = "../utils" } relay-utils = { path = "../utils" }
+52 -2
View File
@@ -14,9 +14,10 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use bp_messages::MessageNonce;
use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf};
use codec::{Codec, Encode}; use codec::{Codec, Encode};
use frame_support::weights::WeightToFeePolynomial; use frame_support::weights::{Weight, WeightToFeePolynomial};
use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize};
use num_traits::Zero; use num_traits::Zero;
use sc_transaction_pool_api::TransactionStatus; use sc_transaction_pool_api::TransactionStatus;
@@ -32,6 +33,11 @@ use std::{fmt::Debug, time::Duration};
pub trait Chain: ChainBase + Clone { pub trait Chain: ChainBase + Clone {
/// Chain name. /// Chain name.
const NAME: &'static str; const NAME: &'static str;
/// Identifier of the basic token of the chain (if applicable).
///
/// This identifier is used to fetch token price. In case of testnets, you may either
/// set it to `None`, or associate testnet with one of the existing tokens.
const TOKEN_ID: Option<&'static str>;
/// Name of the runtime API method that is returning best known finalized header number /// Name of the runtime API method that is returning best known finalized header number
/// and hash (as tuple). /// and hash (as tuple).
/// ///
@@ -52,12 +58,56 @@ pub trait Chain: ChainBase + Clone {
/// Block type. /// Block type.
type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification<Self::Header>; type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification<Self::Header>;
/// The aggregated `Call` type. /// The aggregated `Call` type.
type Call: Clone + Dispatchable + Debug + Send; type Call: Clone + Codec + Dispatchable + Debug + Send;
/// Type that is used by the chain, to convert from weight to fee. /// Type that is used by the chain, to convert from weight to fee.
type WeightToFee: WeightToFeePolynomial<Balance = Self::Balance>; type WeightToFee: WeightToFeePolynomial<Balance = Self::Balance>;
} }
/// Substrate-based chain with messaging support from minimal relay-client point of view.
pub trait ChainWithMessages: Chain {
/// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed
/// at some other chain to bridge with this `ChainWithMessages`.
///
/// We assume that all chains that are bridging with this `ChainWithMessages` are using
/// the same name.
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str;
/// Name of the `To<ChainWithMessages>OutboundLaneApi::message_details` runtime API method.
/// The method is provided by the runtime that is bridged with this `ChainWithMessages`.
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str;
/// Name of the `To<ChainWithMessages>OutboundLaneApi::latest_generated_nonce` runtime API
/// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`.
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str;
/// Name of the `To<ChainWithMessages>OutboundLaneApi::latest_received_nonce` runtime API
/// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`.
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str;
/// Name of the `From<ChainWithMessages>InboundLaneApi::latest_received_nonce` runtime method.
/// The method is provided by the runtime that is bridged with this `ChainWithMessages`.
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str;
/// Name of the `From<ChainWithMessages>InboundLaneApi::latest_confirmed_nonce` runtime method.
/// The method is provided by the runtime that is bridged with this `ChainWithMessages`.
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str;
/// Name of the `From<ChainWithMessages>InboundLaneApi::unrewarded_relayers_state` runtime
/// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`.
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str;
/// Additional weight of the dispatch fee payment if dispatch is paid at the target chain
/// and this `ChainWithMessages` is the target chain.
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight;
/// Maximal number of unrewarded relayers in a single confirmation transaction at this
/// `ChainWithMessages`.
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce;
/// Maximal number of unconfirmed messages in a single confirmation transaction at this
/// `ChainWithMessages`.
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce;
/// Weights of message pallet calls.
type WeightInfo: pallet_bridge_messages::WeightInfoExt;
}
/// Call type used by the chain. /// Call type used by the chain.
pub type CallOf<C> = <C as Chain>::Call; pub type CallOf<C> = <C as Chain>::Call;
/// Weight-to-Fee type used by the chain. /// Weight-to-Fee type used by the chain.
+9 -1
View File
@@ -181,7 +181,7 @@ impl<C: ChainWithBalances> Environment<C> for Client<C> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use frame_support::weights::IdentityFee; use frame_support::weights::{IdentityFee, Weight};
use futures::{ use futures::{
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
future::FutureExt, future::FutureExt,
@@ -202,10 +202,18 @@ mod tests {
type Balance = u32; type Balance = u32;
type Index = u32; type Index = u32;
type Signature = sp_runtime::testing::TestSignature; type Signature = sp_runtime::testing::TestSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
} }
impl Chain for TestChain { impl Chain for TestChain {
const NAME: &'static str = "Test"; const NAME: &'static str = "Test";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader";
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
const STORAGE_PROOF_OVERHEAD: u32 = 0; const STORAGE_PROOF_OVERHEAD: u32 = 0;
+2 -1
View File
@@ -32,7 +32,8 @@ use std::time::Duration;
pub use crate::{ pub use crate::{
chain::{ chain::{
AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances,
TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, ChainWithMessages, TransactionSignScheme, TransactionStatusOf, UnsignedTransaction,
WeightToFeeOf,
}, },
client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription},
error::{Error, Result}, error::{Error, Result},
+1
View File
@@ -16,5 +16,6 @@ bp-westend = { path = "../../primitives/chain-westend" }
# Substrate Dependencies # Substrate Dependencies
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
+10
View File
@@ -16,6 +16,7 @@
//! Types used to connect to the Westend chain. //! Types used to connect to the Westend chain.
use frame_support::weights::Weight;
use relay_substrate_client::{Chain, ChainBase, ChainWithBalances}; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances};
use sp_core::storage::StorageKey; use sp_core::storage::StorageKey;
use std::time::Duration; use std::time::Duration;
@@ -40,10 +41,19 @@ impl ChainBase for Westend {
type Balance = bp_westend::Balance; type Balance = bp_westend::Balance;
type Index = bp_westend::Nonce; type Index = bp_westend::Nonce;
type Signature = bp_westend::Signature; type Signature = bp_westend::Signature;
fn max_extrinsic_size() -> u32 {
bp_westend::Westend::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_westend::Westend::max_extrinsic_weight()
}
} }
impl Chain for Westend { impl Chain for Westend {
const NAME: &'static str = "Westend"; const NAME: &'static str = "Westend";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
+37 -2
View File
@@ -16,10 +16,12 @@
//! Types used to connect to the Wococo-Substrate chain. //! Types used to connect to the Wococo-Substrate chain.
use bp_messages::MessageNonce;
use codec::Encode; use codec::Encode;
use frame_support::weights::Weight;
use relay_substrate_client::{ use relay_substrate_client::{
Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf,
UnsignedTransaction, TransactionSignScheme, UnsignedTransaction,
}; };
use sp_core::{storage::StorageKey, Pair}; use sp_core::{storage::StorageKey, Pair};
use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
@@ -47,10 +49,19 @@ impl ChainBase for Wococo {
type Balance = bp_wococo::Balance; type Balance = bp_wococo::Balance;
type Index = bp_wococo::Nonce; type Index = bp_wococo::Nonce;
type Signature = bp_wococo::Signature; type Signature = bp_wococo::Signature;
fn max_extrinsic_size() -> u32 {
bp_wococo::Wococo::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
bp_wococo::Wococo::max_extrinsic_weight()
}
} }
impl Chain for Wococo { impl Chain for Wococo {
const NAME: &'static str = "Wococo"; const NAME: &'static str = "Wococo";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
@@ -62,6 +73,30 @@ impl Chain for Wococo {
type WeightToFee = bp_wococo::WeightToFee; type WeightToFee = bp_wococo::WeightToFee;
} }
impl ChainWithMessages for Wococo {
const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str =
bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME;
const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str =
bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD;
const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD;
const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str =
bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD;
const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str =
bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD;
const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str =
bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE;
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight =
bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT;
const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce =
bp_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX;
const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce =
bp_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
type WeightInfo = ();
}
impl ChainWithBalances for Wococo { impl ChainWithBalances for Wococo {
fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
StorageKey(bp_wococo::account_info_storage_key(account_id)) StorageKey(bp_wococo::account_info_storage_key(account_id))
+2 -2
View File
@@ -74,7 +74,7 @@ pub enum Call {
BridgeGrandpaRococo(BridgeGrandpaRococoCall), BridgeGrandpaRococo(BridgeGrandpaRococoCall),
/// Rococo messages pallet. /// Rococo messages pallet.
#[codec(index = 43)] #[codec(index = 43)]
BridgeMessagesRococo(BridgeMessagesRococoCall), BridgeRococoMessages(BridgeRococoMessagesCall),
} }
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
@@ -105,7 +105,7 @@ pub enum BridgeGrandpaRococoCall {
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub enum BridgeMessagesRococoCall { pub enum BridgeRococoMessagesCall {
#[codec(index = 3)] #[codec(index = 3)]
send_message( send_message(
LaneId, LaneId,
@@ -42,6 +42,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
[dev-dependencies] [dev-dependencies]
bp-millau = { path = "../../primitives/chain-millau" } bp-millau = { path = "../../primitives/chain-millau" }
bp-rialto = { path = "../../primitives/chain-rialto" }
bp-rococo = { path = "../../primitives/chain-rococo" } bp-rococo = { path = "../../primitives/chain-rococo" }
bp-wococo = { path = "../../primitives/chain-wococo" } bp-wococo = { path = "../../primitives/chain-wococo" }
relay-rococo-client = { path = "../client-rococo" } relay-rococo-client = { path = "../client-rococo" }
@@ -17,7 +17,10 @@
//! Types and functions intended to ease adding of new Substrate -> Substrate //! Types and functions intended to ease adding of new Substrate -> Substrate
//! finality proofs synchronization pipelines. //! finality proofs synchronization pipelines.
use crate::{finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget}; use crate::{
finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget,
TransactionParams,
};
use bp_header_chain::justification::GrandpaJustification; use bp_header_chain::justification::GrandpaJustification;
use finality_relay::FinalitySyncPipeline; use finality_relay::FinalitySyncPipeline;
@@ -36,15 +39,6 @@ use std::{fmt::Debug, marker::PhantomData};
/// Substrate+GRANDPA based chains (good to know). /// Substrate+GRANDPA based chains (good to know).
pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096;
/// Submit-finality-proofs transaction creation parameters.
#[derive(Clone, Debug)]
pub struct TransactionParams<TS> {
/// Transactions author.
pub transactions_signer: TS,
/// Transactions mortality.
pub transactions_mortality: Option<u32>,
}
/// Substrate -> Substrate finality proofs synchronization pipeline. /// Substrate -> Substrate finality proofs synchronization pipeline.
pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync {
/// Headers of this chain are submitted to the `TargetChain`. /// Headers of this chain are submitted to the `TargetChain`.
@@ -67,7 +61,7 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync {
/// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`. /// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FinalitySyncPipelineAdapter<P: SubstrateFinalitySyncPipeline> { pub(crate) struct FinalitySyncPipelineAdapter<P: SubstrateFinalitySyncPipeline> {
_phantom: PhantomData<P>, _phantom: PhantomData<P>,
} }
@@ -179,7 +173,7 @@ where
), ),
recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT,
stall_timeout: transaction_stall_timeout( stall_timeout: transaction_stall_timeout(
transaction_params.transactions_mortality, transaction_params.mortality,
P::TargetChain::AVERAGE_BLOCK_INTERVAL, P::TargetChain::AVERAGE_BLOCK_INTERVAL,
crate::STALL_TIMEOUT, crate::STALL_TIMEOUT,
), ),
@@ -18,8 +18,10 @@
//! bridge GRANDPA pallet deployed and provide `<BridgedChainName>FinalityApi` to allow bridging //! bridge GRANDPA pallet deployed and provide `<BridgedChainName>FinalityApi` to allow bridging
//! with <BridgedName> chain. //! with <BridgedName> chain.
use crate::finality_pipeline::{ use crate::{
FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, finality_pipeline::{
FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline,
},
TransactionParams, TransactionParams,
}; };
@@ -103,16 +105,13 @@ where
P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof);
self.client self.client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.transaction_params.transactions_signer.public().into(), self.transaction_params.signer.public().into(),
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
Bytes( Bytes(
P::TransactionSignScheme::sign_transaction( P::TransactionSignScheme::sign_transaction(
genesis_hash, genesis_hash,
&transaction_params.transactions_signer, &transaction_params.signer,
TransactionEra::new( TransactionEra::new(best_block_id, transaction_params.mortality),
best_block_id,
transaction_params.transactions_mortality,
),
UnsignedTransaction::new(call, transaction_nonce), UnsignedTransaction::new(call, transaction_nonce),
) )
.encode(), .encode(),
@@ -28,6 +28,7 @@ pub mod finality_target;
pub mod headers_initialize; pub mod headers_initialize;
pub mod helpers; pub mod helpers;
pub mod messages_lane; pub mod messages_lane;
pub mod messages_metrics;
pub mod messages_source; pub mod messages_source;
pub mod messages_target; pub mod messages_target;
pub mod on_demand_headers; pub mod on_demand_headers;
@@ -40,3 +41,12 @@ pub mod on_demand_headers;
/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine /// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine
/// transaction, or remove it from the pool. /// transaction, or remove it from the pool.
pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60);
/// Transaction creation parameters.
#[derive(Clone, Debug)]
pub struct TransactionParams<TS> {
/// Transactions author.
pub signer: TS,
/// Transactions mortality.
pub mortality: Option<u32>,
}
@@ -17,194 +17,396 @@
//! Tools for supporting message lanes between two Substrate-based chains. //! Tools for supporting message lanes between two Substrate-based chains.
use crate::{ use crate::{
messages_source::SubstrateMessagesProof, messages_target::SubstrateMessagesReceivingProof, messages_metrics::StandaloneMessagesMetrics,
messages_source::{SubstrateMessagesProof, SubstrateMessagesSource},
messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget},
on_demand_headers::OnDemandHeadersRelay, on_demand_headers::OnDemandHeadersRelay,
TransactionParams, STALL_TIMEOUT,
}; };
use async_trait::async_trait;
use bp_messages::{LaneId, MessageNonce}; use bp_messages::{LaneId, MessageNonce};
use bp_runtime::{AccountIdOf, IndexOf}; use bp_runtime::{AccountIdOf, Chain as _};
use frame_support::weights::Weight; use bridge_runtime_common::messages::{
use messages_relay::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf},
relay_strategy::RelayStrategy,
}; };
use codec::Encode;
use frame_support::weights::{GetDispatchInfo, Weight};
use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy};
use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig};
use relay_substrate_client::{ use relay_substrate_client::{
metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, Client, HashOf,
BlockNumberOf, Chain, Client, HashOf, TransactionSignScheme,
}; };
use relay_utils::{ use relay_utils::metrics::MetricsParams;
metrics::{ use sp_core::Pair;
FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, use std::{convert::TryFrom, fmt::Debug, marker::PhantomData};
},
BlockNumberBase, /// Substrate -> Substrate messages synchronization pipeline.
}; pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync {
use sp_core::{storage::StorageKey, Bytes}; /// Name of the source -> target tokens conversion rate parameter name.
use sp_runtime::FixedU128; ///
use std::ops::RangeInclusive; /// The parameter is stored at the target chain and the storage key is computed using
/// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed
/// to be 1.
const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>;
/// Name of the target -> source tokens conversion rate parameter name.
///
/// The parameter is stored at the source chain and the storage key is computed using
/// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed
/// to be 1.
const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>;
/// Messages of this chain are relayed to the `TargetChain`.
type SourceChain: ChainWithMessages;
/// Messages from the `SourceChain` are dispatched on this chain.
type TargetChain: ChainWithMessages;
/// Scheme used to sign source chain transactions.
type SourceTransactionSignScheme: TransactionSignScheme;
/// Scheme used to sign target chain transactions.
type TargetTransactionSignScheme: TransactionSignScheme;
/// How receive messages proof call is built?
type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder<Self>;
/// How receive messages delivery proof call is built?
type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder<Self>;
/// Message relay strategy.
type RelayStrategy: RelayStrategy;
}
/// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`.
#[derive(Clone, Debug)]
pub(crate) struct MessageLaneAdapter<P: SubstrateMessageLane> {
_phantom: PhantomData<P>,
}
impl<P: SubstrateMessageLane> MessageLane for MessageLaneAdapter<P> {
const SOURCE_NAME: &'static str = P::SourceChain::NAME;
const TARGET_NAME: &'static str = P::TargetChain::NAME;
type MessagesProof = SubstrateMessagesProof<P::SourceChain>;
type MessagesReceivingProof = SubstrateMessagesDeliveryProof<P::TargetChain>;
type SourceChainBalance = BalanceOf<P::SourceChain>;
type SourceHeaderNumber = BlockNumberOf<P::SourceChain>;
type SourceHeaderHash = HashOf<P::SourceChain>;
type TargetHeaderNumber = BlockNumberOf<P::TargetChain>;
type TargetHeaderHash = HashOf<P::TargetChain>;
}
/// Substrate <-> Substrate messages relay parameters. /// Substrate <-> Substrate messages relay parameters.
pub struct MessagesRelayParams<SC: Chain, SS, TC: Chain, TS, Strategy: RelayStrategy> { pub struct MessagesRelayParams<P: SubstrateMessageLane> {
/// Messages source client. /// Messages source client.
pub source_client: Client<SC>, pub source_client: Client<P::SourceChain>,
/// Sign parameters for messages source chain. /// Source transaction params.
pub source_sign: SS, pub source_transaction_params:
/// Mortality of source transactions. TransactionParams<AccountKeyPairOf<P::SourceTransactionSignScheme>>,
pub source_transactions_mortality: Option<u32>,
/// Messages target client. /// Messages target client.
pub target_client: Client<TC>, pub target_client: Client<P::TargetChain>,
/// Sign parameters for messages target chain. /// Target transaction params.
pub target_sign: TS, pub target_transaction_params:
/// Mortality of target transactions. TransactionParams<AccountKeyPairOf<P::TargetTransactionSignScheme>>,
pub target_transactions_mortality: Option<u32>,
/// Optional on-demand source to target headers relay. /// Optional on-demand source to target headers relay.
pub source_to_target_headers_relay: Option<OnDemandHeadersRelay<SC>>, pub source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
/// Optional on-demand target to source headers relay. /// Optional on-demand target to source headers relay.
pub target_to_source_headers_relay: Option<OnDemandHeadersRelay<TC>>, pub target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
/// Identifier of lane that needs to be served. /// Identifier of lane that needs to be served.
pub lane_id: LaneId, pub lane_id: LaneId,
/// Metrics parameters. /// Metrics parameters.
pub metrics_params: MetricsParams, pub metrics_params: MetricsParams,
/// Pre-registered standalone metrics. /// Pre-registered standalone metrics.
pub standalone_metrics: Option<StandaloneMessagesMetrics<SC, TC>>, pub standalone_metrics: Option<StandaloneMessagesMetrics<P::SourceChain, P::TargetChain>>,
/// Relay strategy /// Relay strategy.
pub relay_strategy: Strategy, pub relay_strategy: P::RelayStrategy,
} }
/// Message sync pipeline for Substrate <-> Substrate relays. /// Run Substrate-to-Substrate messages sync loop.
#[async_trait] pub async fn run<P: SubstrateMessageLane>(params: MessagesRelayParams<P>) -> anyhow::Result<()>
pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { where
/// Underlying generic message lane. AccountIdOf<P::SourceChain>:
type MessageLane: MessageLane; From<<AccountKeyPairOf<P::SourceTransactionSignScheme> as Pair>::Public>,
AccountIdOf<P::TargetChain>:
/// Name of the runtime method that returns dispatch weight of outbound messages at the source From<<AccountKeyPairOf<P::TargetTransactionSignScheme> as Pair>::Public>,
/// chain. BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>>,
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; P::SourceTransactionSignScheme: TransactionSignScheme<Chain = P::SourceChain>,
/// Name of the runtime method that returns latest generated nonce at the source chain. P::TargetTransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str;
/// Name of the runtime method that returns latest received (confirmed) nonce at the the source
/// chain.
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str;
/// Name of the runtime method that returns latest received nonce at the target chain.
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str;
/// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the
/// target chain.
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str;
/// Number of the runtime method that returns state of "unrewarded relayers" set at the target
/// chain.
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str;
/// Name of the runtime method that returns id of best finalized source header at target chain.
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str;
/// Name of the runtime method that returns id of best finalized target header at source chain.
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str;
/// Name of the messages pallet as it is declared in the `construct_runtime!()` at source chain.
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str;
/// Name of the messages pallet as it is declared in the `construct_runtime!()` at target chain.
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str;
/// Extra weight of the delivery transaction at the target chain, that is paid to cover
/// dispatch fee payment.
///
/// If dispatch fee is paid at the source chain, then this weight is refunded by the
/// delivery transaction.
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight;
/// Source chain.
type SourceChain: Chain;
/// Target chain.
type TargetChain: Chain;
/// Returns id of account that we're using to sign transactions at target chain (messages
/// proof).
fn target_transactions_author(&self) -> AccountIdOf<Self::TargetChain>;
/// Make messages delivery transaction.
fn make_messages_delivery_transaction(
&self,
best_block_id: TargetHeaderIdOf<Self::MessageLane>,
transaction_nonce: IndexOf<Self::TargetChain>,
generated_at_header: SourceHeaderIdOf<Self::MessageLane>,
nonces: RangeInclusive<MessageNonce>,
proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes;
/// Returns id of account that we're using to sign transactions at source chain (delivery
/// proof).
fn source_transactions_author(&self) -> AccountIdOf<Self::SourceChain>;
/// Make messages receiving proof transaction.
fn make_messages_receiving_proof_transaction(
&self,
best_block_id: SourceHeaderIdOf<Self::MessageLane>,
transaction_nonce: IndexOf<Self::SourceChain>,
generated_at_header: TargetHeaderIdOf<Self::MessageLane>,
proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes;
}
/// Substrate-to-Substrate message lane.
#[derive(Debug)]
pub struct SubstrateMessageLaneToSubstrate<
Source: Chain,
SourceSignParams,
Target: Chain,
TargetSignParams,
> {
/// Client for the source Substrate chain.
pub source_client: Client<Source>,
/// Parameters required to sign transactions for source chain.
pub source_sign: SourceSignParams,
/// Source transactions mortality.
pub source_transactions_mortality: Option<u32>,
/// Client for the target Substrate chain.
pub target_client: Client<Target>,
/// Parameters required to sign transactions for target chain.
pub target_sign: TargetSignParams,
/// Target transactions mortality.
pub target_transactions_mortality: Option<u32>,
/// Account id of relayer at the source chain.
pub relayer_id_at_source: Source::AccountId,
}
impl<Source: Chain, SourceSignParams: Clone, Target: Chain, TargetSignParams: Clone> Clone
for SubstrateMessageLaneToSubstrate<Source, SourceSignParams, Target, TargetSignParams>
{ {
fn clone(&self) -> Self { let source_client = params.source_client;
Self { let target_client = params.target_client;
source_client: self.source_client.clone(), let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout(
source_sign: self.source_sign.clone(), params.source_transaction_params.mortality,
source_transactions_mortality: self.source_transactions_mortality, params.target_transaction_params.mortality,
target_client: self.target_client.clone(), P::SourceChain::AVERAGE_BLOCK_INTERVAL,
target_sign: self.target_sign.clone(), P::TargetChain::AVERAGE_BLOCK_INTERVAL,
target_transactions_mortality: self.target_transactions_mortality, STALL_TIMEOUT,
relayer_id_at_source: self.relayer_id_at_source.clone(), );
let relayer_id_at_source: AccountIdOf<P::SourceChain> =
params.source_transaction_params.signer.public().into();
// 2/3 is reserved for proofs and tx overhead
let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3;
// we don't know exact weights of the Polkadot 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) =
crate::messages_lane::select_delivery_transaction_limits::<
<P::TargetChain as ChainWithMessages>::WeightInfo,
>(
P::TargetChain::max_extrinsic_weight(),
P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
);
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);
let standalone_metrics = params.standalone_metrics.map(Ok).unwrap_or_else(|| {
crate::messages_metrics::standalone_metrics::<P>(
source_client.clone(),
target_client.clone(),
)
})?;
log::info!(
target: "bridge",
"Starting {} -> {} messages relay.\n\t\
{} 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: {}\n\t\
Tx mortality: {:?}/{:?}\n\t\
Stall timeout: {:?}",
P::SourceChain::NAME,
P::TargetChain::NAME,
P::SourceChain::NAME,
relayer_id_at_source,
max_messages_in_single_batch,
max_messages_size_in_single_batch,
max_messages_weight_in_single_batch,
params.source_transaction_params.mortality,
params.target_transaction_params.mortality,
stall_timeout,
);
messages_relay::message_lane_loop::run(
messages_relay::message_lane_loop::Params {
lane: params.lane_id,
source_tick: P::SourceChain::AVERAGE_BLOCK_INTERVAL,
target_tick: P::TargetChain::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:
P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
max_unconfirmed_nonces_at_target:
P::SourceChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX,
max_messages_in_single_batch,
max_messages_weight_in_single_batch,
max_messages_size_in_single_batch,
relay_strategy: params.relay_strategy,
},
},
SubstrateMessagesSource::<P>::new(
source_client,
params.lane_id,
params.source_transaction_params,
params.target_to_source_headers_relay,
),
SubstrateMessagesTarget::<P>::new(
target_client,
params.lane_id,
relayer_id_at_source,
params.target_transaction_params,
standalone_metrics.clone(),
params.source_to_target_headers_relay,
),
standalone_metrics.register_and_spawn(params.metrics_params)?,
futures::future::pending(),
)
.await
.map_err(Into::into)
}
/// Different ways of building `receive_messages_proof` calls.
pub trait ReceiveMessagesProofCallBuilder<P: SubstrateMessageLane> {
/// Given messages proof, build call of `receive_messages_proof` function of bridge
/// messages module at the target chain.
fn build_receive_messages_proof_call(
relayer_id_at_source: AccountIdOf<P::SourceChain>,
proof: SubstrateMessagesProof<P::SourceChain>,
messages_count: u32,
dispatch_weight: Weight,
trace_call: bool,
) -> CallOf<P::TargetChain>;
}
/// Building `receive_messages_proof` call when you have direct access to the target
/// chain runtime.
pub struct DirectReceiveMessagesProofCallBuilder<P, R, I> {
_phantom: PhantomData<(P, R, I)>,
}
impl<P, R, I> ReceiveMessagesProofCallBuilder<P> for DirectReceiveMessagesProofCallBuilder<P, R, I>
where
P: SubstrateMessageLane,
R: BridgeMessagesConfig<I, InboundRelayer = AccountIdOf<P::SourceChain>>,
I: 'static,
R::SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain<
R::InboundMessageFee,
MessagesProof = FromBridgedChainMessagesProof<HashOf<P::SourceChain>>,
>,
CallOf<P::TargetChain>: From<BridgeMessagesCall<R, I>> + GetDispatchInfo,
{
fn build_receive_messages_proof_call(
relayer_id_at_source: AccountIdOf<P::SourceChain>,
proof: SubstrateMessagesProof<P::SourceChain>,
messages_count: u32,
dispatch_weight: Weight,
trace_call: bool,
) -> CallOf<P::TargetChain> {
let call: CallOf<P::TargetChain> = BridgeMessagesCall::<R, I>::receive_messages_proof {
relayer_id_at_bridged_chain: relayer_id_at_source,
proof: proof.1,
messages_count,
dispatch_weight,
} }
.into();
if trace_call {
// this trace isn't super-accurate, because limits are for transactions and we
// have a call here, but it provides required information
log::trace!(
target: "bridge",
"Prepared {} -> {} messages delivery call. Weight: {}/{}, size: {}/{}",
P::SourceChain::NAME,
P::TargetChain::NAME,
call.get_dispatch_info().weight,
P::TargetChain::max_extrinsic_weight(),
call.encode().len(),
P::TargetChain::max_extrinsic_size(),
);
}
call
} }
} }
impl<Source: Chain, SourceSignParams, Target: Chain, TargetSignParams> MessageLane /// Macro that generates `ReceiveMessagesProofCallBuilder` implementation for the case when
for SubstrateMessageLaneToSubstrate<Source, SourceSignParams, Target, TargetSignParams> /// you only have an access to the mocked version of target chain runtime. In this case you
/// should provide "name" of the call variant for the bridge messages calls and the "name" of
/// the variant for the `receive_messages_proof` call within that first option.
#[rustfmt::skip]
#[macro_export]
macro_rules! generate_mocked_receive_message_proof_call_builder {
($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_proof:path) => {
pub struct $mocked_builder;
impl $crate::messages_lane::ReceiveMessagesProofCallBuilder<$pipeline>
for $mocked_builder
{
fn build_receive_messages_proof_call(
relayer_id_at_source: relay_substrate_client::AccountIdOf<
<$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain
>,
proof: $crate::messages_source::SubstrateMessagesProof<
<$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain
>,
messages_count: u32,
dispatch_weight: Weight,
_trace_call: bool,
) -> relay_substrate_client::CallOf<
<$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain
> {
$bridge_messages($receive_messages_proof(
relayer_id_at_source,
proof.1,
messages_count,
dispatch_weight,
))
}
}
};
}
/// Different ways of building `receive_messages_delivery_proof` calls.
pub trait ReceiveMessagesDeliveryProofCallBuilder<P: SubstrateMessageLane> {
/// Given messages delivery proof, build call of `receive_messages_delivery_proof` function of
/// bridge messages module at the source chain.
fn build_receive_messages_delivery_proof_call(
proof: SubstrateMessagesDeliveryProof<P::TargetChain>,
trace_call: bool,
) -> CallOf<P::SourceChain>;
}
/// Building `receive_messages_delivery_proof` call when you have direct access to the source
/// chain runtime.
pub struct DirectReceiveMessagesDeliveryProofCallBuilder<P, R, I> {
_phantom: PhantomData<(P, R, I)>,
}
impl<P, R, I> ReceiveMessagesDeliveryProofCallBuilder<P>
for DirectReceiveMessagesDeliveryProofCallBuilder<P, R, I>
where where
SourceSignParams: Clone + Send + Sync + 'static, P: SubstrateMessageLane,
TargetSignParams: Clone + Send + Sync + 'static, R: BridgeMessagesConfig<I>,
BlockNumberOf<Source>: BlockNumberBase, I: 'static,
BlockNumberOf<Target>: BlockNumberBase, R::TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain<
R::OutboundPayload,
R::AccountId,
MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof<HashOf<P::TargetChain>>,
>,
CallOf<P::SourceChain>: From<BridgeMessagesCall<R, I>> + GetDispatchInfo,
{ {
const SOURCE_NAME: &'static str = Source::NAME; fn build_receive_messages_delivery_proof_call(
const TARGET_NAME: &'static str = Target::NAME; proof: SubstrateMessagesDeliveryProof<P::TargetChain>,
trace_call: bool,
) -> CallOf<P::SourceChain> {
let call: CallOf<P::SourceChain> =
BridgeMessagesCall::<R, I>::receive_messages_delivery_proof {
proof: proof.1,
relayers_state: proof.0,
}
.into();
if trace_call {
// this trace isn't super-accurate, because limits are for transactions and we
// have a call here, but it provides required information
log::trace!(
target: "bridge",
"Prepared {} -> {} delivery confirmation transaction. Weight: {}/{}, size: {}/{}",
P::TargetChain::NAME,
P::SourceChain::NAME,
call.get_dispatch_info().weight,
P::SourceChain::max_extrinsic_weight(),
call.encode().len(),
P::SourceChain::max_extrinsic_size(),
);
}
call
}
}
type MessagesProof = SubstrateMessagesProof<Source>; /// Macro that generates `ReceiveMessagesDeliveryProofCallBuilder` implementation for the case when
type MessagesReceivingProof = SubstrateMessagesReceivingProof<Target>; /// you only have an access to the mocked version of source chain runtime. In this case you
/// should provide "name" of the call variant for the bridge messages calls and the "name" of
/// the variant for the `receive_messages_delivery_proof` call within that first option.
#[rustfmt::skip]
#[macro_export]
macro_rules! generate_mocked_receive_message_delivery_proof_call_builder {
($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_delivery_proof:path) => {
pub struct $mocked_builder;
type SourceChainBalance = Source::Balance; impl $crate::messages_lane::ReceiveMessagesDeliveryProofCallBuilder<$pipeline>
type SourceHeaderNumber = BlockNumberOf<Source>; for $mocked_builder
type SourceHeaderHash = HashOf<Source>; {
fn build_receive_messages_delivery_proof_call(
type TargetHeaderNumber = BlockNumberOf<Target>; proof: $crate::messages_target::SubstrateMessagesDeliveryProof<
type TargetHeaderHash = HashOf<Target>; <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain
>,
_trace_call: bool,
) -> relay_substrate_client::CallOf<
<$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain
> {
$bridge_messages($receive_messages_delivery_proof(proof.1, proof.0))
}
}
};
} }
/// Returns maximal number of messages and their maximal cumulative dispatch weight, based /// Returns maximal number of messages and their maximal cumulative dispatch weight, based
@@ -245,155 +447,10 @@ pub fn select_delivery_transaction_limits<W: pallet_bridge_messages::WeightInfoE
(max_number_of_messages, weight_for_messages_dispatch) (max_number_of_messages, weight_for_messages_dispatch)
} }
/// Shared references to the standalone metrics of the message lane relay loop.
#[derive(Debug, Clone)]
pub struct StandaloneMessagesMetrics<SC: Chain, TC: Chain> {
/// Global metrics.
pub global: GlobalMetrics,
/// Storage chain proof overhead metric.
pub source_storage_proof_overhead: StorageProofOverheadMetric<SC>,
/// Target chain proof overhead metric.
pub target_storage_proof_overhead: StorageProofOverheadMetric<TC>,
/// Source tokens to base conversion rate metric.
pub source_to_base_conversion_rate: Option<FloatJsonValueMetric>,
/// Target tokens to base conversion rate metric.
pub target_to_base_conversion_rate: Option<FloatJsonValueMetric>,
/// Source tokens to target tokens conversion rate metric. This rate is stored by the target
/// chain.
pub source_to_target_conversion_rate:
Option<FloatStorageValueMetric<TC, sp_runtime::FixedU128>>,
/// Target tokens to source tokens conversion rate metric. This rate is stored by the source
/// chain.
pub target_to_source_conversion_rate:
Option<FloatStorageValueMetric<SC, sp_runtime::FixedU128>>,
}
impl<SC: Chain, TC: Chain> StandaloneMessagesMetrics<SC, TC> {
/// Swap source and target sides.
pub fn reverse(self) -> StandaloneMessagesMetrics<TC, SC> {
StandaloneMessagesMetrics {
global: self.global,
source_storage_proof_overhead: self.target_storage_proof_overhead,
target_storage_proof_overhead: self.source_storage_proof_overhead,
source_to_base_conversion_rate: self.target_to_base_conversion_rate,
target_to_base_conversion_rate: self.source_to_base_conversion_rate,
source_to_target_conversion_rate: self.target_to_source_conversion_rate,
target_to_source_conversion_rate: self.source_to_target_conversion_rate,
}
}
/// Register all metrics in the registry.
pub fn register_and_spawn(
self,
metrics: MetricsParams,
) -> Result<MetricsParams, PrometheusError> {
self.global.register_and_spawn(&metrics.registry)?;
self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?;
self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?;
if let Some(m) = self.source_to_base_conversion_rate {
m.register_and_spawn(&metrics.registry)?;
}
if let Some(m) = self.target_to_base_conversion_rate {
m.register_and_spawn(&metrics.registry)?;
}
if let Some(m) = self.target_to_source_conversion_rate {
m.register_and_spawn(&metrics.registry)?;
}
Ok(metrics)
}
/// Return conversion rate from target to source tokens.
pub async fn target_to_source_conversion_rate(&self) -> Option<f64> {
Self::compute_target_to_source_conversion_rate(
*self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await,
*self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await,
)
}
/// Return conversion rate from target to source tokens, given conversion rates from
/// target/source tokens to some base token.
fn compute_target_to_source_conversion_rate(
target_to_base_conversion_rate: Option<f64>,
source_to_base_conversion_rate: Option<f64>,
) -> Option<f64> {
Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?)
}
}
/// Create standalone metrics for the message lane relay loop.
///
/// All metrics returned by this function are exposed by loops that are serving given lane (`P`)
/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`).
pub fn standalone_metrics<SC: Chain, TC: Chain>(
source_client: Client<SC>,
target_client: Client<TC>,
source_chain_token_id: Option<&str>,
target_chain_token_id: Option<&str>,
source_to_target_conversion_rate_params: Option<(StorageKey, FixedU128)>,
target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>,
) -> anyhow::Result<StandaloneMessagesMetrics<SC, TC>> {
Ok(StandaloneMessagesMetrics {
global: GlobalMetrics::new()?,
source_storage_proof_overhead: StorageProofOverheadMetric::new(
source_client.clone(),
format!("{}_storage_proof_overhead", SC::NAME.to_lowercase()),
format!("{} storage proof overhead", SC::NAME),
)?,
target_storage_proof_overhead: StorageProofOverheadMetric::new(
target_client.clone(),
format!("{}_storage_proof_overhead", TC::NAME.to_lowercase()),
format!("{} storage proof overhead", TC::NAME),
)?,
source_to_base_conversion_rate: source_chain_token_id
.map(|source_chain_token_id| {
crate::helpers::token_price_metric(source_chain_token_id).map(Some)
})
.unwrap_or(Ok(None))?,
target_to_base_conversion_rate: target_chain_token_id
.map(|target_chain_token_id| {
crate::helpers::token_price_metric(target_chain_token_id).map(Some)
})
.unwrap_or(Ok(None))?,
source_to_target_conversion_rate: source_to_target_conversion_rate_params
.map(|(key, rate)| {
FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new(
target_client,
key,
Some(rate),
format!("{}_{}_to_{}_conversion_rate", TC::NAME, SC::NAME, TC::NAME),
format!(
"{} to {} tokens conversion rate (used by {})",
SC::NAME,
TC::NAME,
TC::NAME
),
)
.map(Some)
})
.unwrap_or(Ok(None))?,
target_to_source_conversion_rate: target_to_source_conversion_rate_params
.map(|(key, rate)| {
FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new(
source_client,
key,
Some(rate),
format!("{}_{}_to_{}_conversion_rate", SC::NAME, TC::NAME, SC::NAME),
format!(
"{} to {} tokens conversion rate (used by {})",
TC::NAME,
SC::NAME,
SC::NAME
),
)
.map(Some)
})
.unwrap_or(Ok(None))?,
})
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use bp_runtime::Chain;
type RialtoToMillauMessagesWeights = type RialtoToMillauMessagesWeights =
pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>; pallet_bridge_messages::weights::RialtoWeight<rialto_runtime::Runtime>;
@@ -402,8 +459,8 @@ mod tests {
fn select_delivery_transaction_limits_works() { fn select_delivery_transaction_limits_works() {
let (max_count, max_weight) = let (max_count, max_weight) =
select_delivery_transaction_limits::<RialtoToMillauMessagesWeights>( select_delivery_transaction_limits::<RialtoToMillauMessagesWeights>(
bp_millau::max_extrinsic_weight(), bp_millau::Millau::max_extrinsic_weight(),
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX,
); );
assert_eq!( assert_eq!(
(max_count, max_weight), (max_count, max_weight),
@@ -415,12 +472,4 @@ mod tests {
(782, 216_583_333_334), (782, 216_583_333_334),
); );
} }
#[async_std::test]
async fn target_to_source_conversion_rate_works() {
assert_eq!(
StandaloneMessagesMetrics::<relay_rococo_client::Rococo, relay_wococo_client::Wococo>::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)),
Some(12.32 / 183.15),
);
}
} }
@@ -0,0 +1,199 @@
// 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/>.
//! Tools for supporting message lanes between two Substrate-based chains.
use crate::messages_lane::SubstrateMessageLane;
use num_traits::One;
use relay_substrate_client::{
metrics::{FloatStorageValueMetric, StorageProofOverheadMetric},
Chain, Client,
};
use relay_utils::metrics::{
FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric,
};
use sp_runtime::FixedU128;
use std::fmt::Debug;
/// Shared references to the standalone metrics of the message lane relay loop.
#[derive(Debug, Clone)]
pub struct StandaloneMessagesMetrics<SC: Chain, TC: Chain> {
/// Global metrics.
pub global: GlobalMetrics,
/// Storage chain proof overhead metric.
pub source_storage_proof_overhead: StorageProofOverheadMetric<SC>,
/// Target chain proof overhead metric.
pub target_storage_proof_overhead: StorageProofOverheadMetric<TC>,
/// Source tokens to base conversion rate metric.
pub source_to_base_conversion_rate: Option<FloatJsonValueMetric>,
/// Target tokens to base conversion rate metric.
pub target_to_base_conversion_rate: Option<FloatJsonValueMetric>,
/// Source tokens to target tokens conversion rate metric. This rate is stored by the target
/// chain.
pub source_to_target_conversion_rate:
Option<FloatStorageValueMetric<TC, sp_runtime::FixedU128>>,
/// Target tokens to source tokens conversion rate metric. This rate is stored by the source
/// chain.
pub target_to_source_conversion_rate:
Option<FloatStorageValueMetric<SC, sp_runtime::FixedU128>>,
}
impl<SC: Chain, TC: Chain> StandaloneMessagesMetrics<SC, TC> {
/// Swap source and target sides.
pub fn reverse(self) -> StandaloneMessagesMetrics<TC, SC> {
StandaloneMessagesMetrics {
global: self.global,
source_storage_proof_overhead: self.target_storage_proof_overhead,
target_storage_proof_overhead: self.source_storage_proof_overhead,
source_to_base_conversion_rate: self.target_to_base_conversion_rate,
target_to_base_conversion_rate: self.source_to_base_conversion_rate,
source_to_target_conversion_rate: self.target_to_source_conversion_rate,
target_to_source_conversion_rate: self.source_to_target_conversion_rate,
}
}
/// Register all metrics in the registry.
pub fn register_and_spawn(
self,
metrics: MetricsParams,
) -> Result<MetricsParams, PrometheusError> {
self.global.register_and_spawn(&metrics.registry)?;
self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?;
self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?;
if let Some(m) = self.source_to_base_conversion_rate {
m.register_and_spawn(&metrics.registry)?;
}
if let Some(m) = self.target_to_base_conversion_rate {
m.register_and_spawn(&metrics.registry)?;
}
if let Some(m) = self.target_to_source_conversion_rate {
m.register_and_spawn(&metrics.registry)?;
}
Ok(metrics)
}
/// Return conversion rate from target to source tokens.
pub async fn target_to_source_conversion_rate(&self) -> Option<f64> {
Self::compute_target_to_source_conversion_rate(
*self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await,
*self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await,
)
}
/// Return conversion rate from target to source tokens, given conversion rates from
/// target/source tokens to some base token.
fn compute_target_to_source_conversion_rate(
target_to_base_conversion_rate: Option<f64>,
source_to_base_conversion_rate: Option<f64>,
) -> Option<f64> {
Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?)
}
}
/// Create standalone metrics for the message lane relay loop.
///
/// All metrics returned by this function are exposed by loops that are serving given lane (`P`)
/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`).
/// We assume that either conversion rate parameters have values in the storage, or they are
/// initialized with 1:1.
pub fn standalone_metrics<P: SubstrateMessageLane>(
source_client: Client<P::SourceChain>,
target_client: Client<P::TargetChain>,
) -> anyhow::Result<StandaloneMessagesMetrics<P::SourceChain, P::TargetChain>> {
Ok(StandaloneMessagesMetrics {
global: GlobalMetrics::new()?,
source_storage_proof_overhead: StorageProofOverheadMetric::new(
source_client.clone(),
format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()),
format!("{} storage proof overhead", P::SourceChain::NAME),
)?,
target_storage_proof_overhead: StorageProofOverheadMetric::new(
target_client.clone(),
format!("{}_storage_proof_overhead", P::TargetChain::NAME.to_lowercase()),
format!("{} storage proof overhead", P::TargetChain::NAME),
)?,
source_to_base_conversion_rate: P::SourceChain::TOKEN_ID
.map(|source_chain_token_id| {
crate::helpers::token_price_metric(source_chain_token_id).map(Some)
})
.unwrap_or(Ok(None))?,
target_to_base_conversion_rate: P::TargetChain::TOKEN_ID
.map(|target_chain_token_id| {
crate::helpers::token_price_metric(target_chain_token_id).map(Some)
})
.unwrap_or(Ok(None))?,
source_to_target_conversion_rate: P::SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME
.map(bp_runtime::storage_parameter_key)
.map(|key| {
FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new(
target_client,
key,
Some(FixedU128::one()),
format!(
"{}_{}_to_{}_conversion_rate",
P::TargetChain::NAME,
P::SourceChain::NAME,
P::TargetChain::NAME
),
format!(
"{} to {} tokens conversion rate (used by {})",
P::SourceChain::NAME,
P::TargetChain::NAME,
P::TargetChain::NAME
),
)
.map(Some)
})
.unwrap_or(Ok(None))?,
target_to_source_conversion_rate: P::TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME
.map(bp_runtime::storage_parameter_key)
.map(|key| {
FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new(
source_client,
key,
Some(FixedU128::one()),
format!(
"{}_{}_to_{}_conversion_rate",
P::SourceChain::NAME,
P::TargetChain::NAME,
P::SourceChain::NAME
),
format!(
"{} to {} tokens conversion rate (used by {})",
P::TargetChain::NAME,
P::SourceChain::NAME,
P::SourceChain::NAME
),
)
.map(Some)
})
.unwrap_or(Ok(None))?,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[async_std::test]
async fn target_to_source_conversion_rate_works() {
assert_eq!(
StandaloneMessagesMetrics::<relay_rococo_client::Rococo, relay_wococo_client::Wococo>::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)),
Some(12.32 / 183.15),
);
}
}
@@ -19,8 +19,12 @@
//! <BridgedName> chain. //! <BridgedName> chain.
use crate::{ use crate::{
messages_lane::SubstrateMessageLane, messages_target::SubstrateMessagesReceivingProof, messages_lane::{
MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane,
},
messages_target::SubstrateMessagesDeliveryProof,
on_demand_headers::OnDemandHeadersRelay, on_demand_headers::OnDemandHeadersRelay,
TransactionParams,
}; };
use async_trait::async_trait; use async_trait::async_trait;
@@ -39,15 +43,13 @@ use messages_relay::{
}; };
use num_traits::{Bounded, Zero}; use num_traits::{Bounded, Zero};
use relay_substrate_client::{ use relay_substrate_client::{
BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client,
IndexOf, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme,
}; UnsignedTransaction,
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId};
use sp_core::Bytes;
use sp_runtime::{
traits::{AtLeast32BitUnsigned, Header as HeaderT},
DeserializeOwned,
}; };
use relay_utils::{relay_loop::Client as RelayClient, HeaderId};
use sp_core::{Bytes, Pair};
use sp_runtime::{traits::Header as HeaderT, DeserializeOwned};
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
/// Intermediate message proof returned by the source Substrate node. Includes everything /// Intermediate message proof returned by the source Substrate node. Includes everything
@@ -58,8 +60,8 @@ pub type SubstrateMessagesProof<C> = (Weight, FromBridgedChainMessagesProof<Hash
/// Substrate client as Substrate messages source. /// Substrate client as Substrate messages source.
pub struct SubstrateMessagesSource<P: SubstrateMessageLane> { pub struct SubstrateMessagesSource<P: SubstrateMessageLane> {
client: Client<P::SourceChain>, client: Client<P::SourceChain>,
lane: P,
lane_id: LaneId, lane_id: LaneId,
transaction_params: TransactionParams<AccountKeyPairOf<P::SourceTransactionSignScheme>>,
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>, target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
} }
@@ -67,11 +69,16 @@ impl<P: SubstrateMessageLane> SubstrateMessagesSource<P> {
/// Create new Substrate headers source. /// Create new Substrate headers source.
pub fn new( pub fn new(
client: Client<P::SourceChain>, client: Client<P::SourceChain>,
lane: P,
lane_id: LaneId, lane_id: LaneId,
transaction_params: TransactionParams<AccountKeyPairOf<P::SourceTransactionSignScheme>>,
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>, target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
) -> Self { ) -> Self {
SubstrateMessagesSource { client, lane, lane_id, target_to_source_headers_relay } SubstrateMessagesSource {
client,
lane_id,
transaction_params,
target_to_source_headers_relay,
}
} }
} }
@@ -79,8 +86,8 @@ impl<P: SubstrateMessageLane> Clone for SubstrateMessagesSource<P> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
client: self.client.clone(), client: self.client.clone(),
lane: self.lane.clone(),
lane_id: self.lane_id, lane_id: self.lane_id,
transaction_params: self.transaction_params.clone(),
target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), target_to_source_headers_relay: self.target_to_source_headers_relay.clone(),
} }
} }
@@ -96,53 +103,33 @@ impl<P: SubstrateMessageLane> RelayClient for SubstrateMessagesSource<P> {
} }
#[async_trait] #[async_trait]
impl<P> SourceClient<P::MessageLane> for SubstrateMessagesSource<P> impl<P: SubstrateMessageLane> SourceClient<MessageLaneAdapter<P>> for SubstrateMessagesSource<P>
where where
P: SubstrateMessageLane, AccountIdOf<P::SourceChain>:
P::SourceChain: Chain< From<<AccountKeyPairOf<P::SourceTransactionSignScheme> as Pair>::Public>,
Hash = <P::MessageLane as MessageLane>::SourceHeaderHash, P::SourceTransactionSignScheme: TransactionSignScheme<Chain = P::SourceChain>,
BlockNumber = <P::MessageLane as MessageLane>::SourceHeaderNumber,
Balance = <P::MessageLane as MessageLane>::SourceChainBalance,
>,
BalanceOf<P::SourceChain>: Decode + Bounded,
IndexOf<P::SourceChain>: DeserializeOwned,
HashOf<P::SourceChain>: Copy,
BlockNumberOf<P::SourceChain>: BlockNumberBase + Copy,
HeaderOf<P::SourceChain>: DeserializeOwned,
P::TargetChain: Chain<
Hash = <P::MessageLane as MessageLane>::TargetHeaderHash,
BlockNumber = <P::MessageLane as MessageLane>::TargetHeaderNumber,
>,
P::MessageLane: MessageLane<
MessagesProof = SubstrateMessagesProof<P::SourceChain>,
MessagesReceivingProof = SubstrateMessagesReceivingProof<P::TargetChain>,
>,
<P::MessageLane as MessageLane>::TargetHeaderNumber: Decode,
<P::MessageLane as MessageLane>::TargetHeaderHash: Decode,
<P::MessageLane as MessageLane>::SourceChainBalance: AtLeast32BitUnsigned,
{ {
async fn state(&self) -> Result<SourceClientState<P::MessageLane>, SubstrateError> { async fn state(&self) -> Result<SourceClientState<MessageLaneAdapter<P>>, SubstrateError> {
// we can't continue to deliver confirmations if source node is out of sync, because // we can't continue to deliver confirmations if source node is out of sync, because
// it may have already received confirmations that we're going to deliver // it may have already received confirmations that we're going to deliver
self.client.ensure_synced().await?; self.client.ensure_synced().await?;
read_client_state::< read_client_state::<
_, _,
<P::MessageLane as MessageLane>::TargetHeaderHash, <MessageLaneAdapter<P> as MessageLane>::TargetHeaderHash,
<P::MessageLane as MessageLane>::TargetHeaderNumber, <MessageLaneAdapter<P> as MessageLane>::TargetHeaderNumber,
>(&self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE) >(&self.client, P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD)
.await .await
} }
async fn latest_generated_nonce( async fn latest_generated_nonce(
&self, &self,
id: SourceHeaderIdOf<P::MessageLane>, id: SourceHeaderIdOf<MessageLaneAdapter<P>>,
) -> Result<(SourceHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> { ) -> Result<(SourceHeaderIdOf<MessageLaneAdapter<P>>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
P::OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD.into(), P::TargetChain::TO_CHAIN_LATEST_GENERATED_NONCE_METHOD.into(),
Bytes(self.lane_id.encode()), Bytes(self.lane_id.encode()),
Some(id.1), Some(id.1),
) )
@@ -154,12 +141,12 @@ where
async fn latest_confirmed_received_nonce( async fn latest_confirmed_received_nonce(
&self, &self,
id: SourceHeaderIdOf<P::MessageLane>, id: SourceHeaderIdOf<MessageLaneAdapter<P>>,
) -> Result<(SourceHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> { ) -> Result<(SourceHeaderIdOf<MessageLaneAdapter<P>>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
P::OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), P::TargetChain::TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(),
Bytes(self.lane_id.encode()), Bytes(self.lane_id.encode()),
Some(id.1), Some(id.1),
) )
@@ -171,16 +158,16 @@ where
async fn generated_message_details( async fn generated_message_details(
&self, &self,
id: SourceHeaderIdOf<P::MessageLane>, id: SourceHeaderIdOf<MessageLaneAdapter<P>>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
) -> Result< ) -> Result<
MessageDetailsMap<<P::MessageLane as MessageLane>::SourceChainBalance>, MessageDetailsMap<<MessageLaneAdapter<P> as MessageLane>::SourceChainBalance>,
SubstrateError, SubstrateError,
> { > {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
P::OUTBOUND_LANE_MESSAGE_DETAILS_METHOD.into(), P::TargetChain::TO_CHAIN_MESSAGE_DETAILS_METHOD.into(),
Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Bytes((self.lane_id, nonces.start(), nonces.end()).encode()),
Some(id.1), Some(id.1),
) )
@@ -195,14 +182,14 @@ where
async fn prove_messages( async fn prove_messages(
&self, &self,
id: SourceHeaderIdOf<P::MessageLane>, id: SourceHeaderIdOf<MessageLaneAdapter<P>>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
proof_parameters: MessageProofParameters, proof_parameters: MessageProofParameters,
) -> Result< ) -> Result<
( (
SourceHeaderIdOf<P::MessageLane>, SourceHeaderIdOf<MessageLaneAdapter<P>>,
RangeInclusive<MessageNonce>, RangeInclusive<MessageNonce>,
<P::MessageLane as MessageLane>::MessagesProof, <MessageLaneAdapter<P> as MessageLane>::MessagesProof,
), ),
SubstrateError, SubstrateError,
> { > {
@@ -211,7 +198,7 @@ where
let mut message_nonce = *nonces.start(); let mut message_nonce = *nonces.start();
while message_nonce <= *nonces.end() { while message_nonce <= *nonces.end() {
let message_key = pallet_bridge_messages::storage_keys::message_key( let message_key = pallet_bridge_messages::storage_keys::message_key(
P::MESSAGE_PALLET_NAME_AT_SOURCE, P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME,
&self.lane_id, &self.lane_id,
message_nonce, message_nonce,
); );
@@ -220,7 +207,7 @@ where
} }
if proof_parameters.outbound_state_proof_required { if proof_parameters.outbound_state_proof_required {
storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key( storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key(
P::MESSAGE_PALLET_NAME_AT_SOURCE, P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME,
&self.lane_id, &self.lane_id,
)); ));
} }
@@ -238,19 +225,22 @@ where
async fn submit_messages_receiving_proof( async fn submit_messages_receiving_proof(
&self, &self,
generated_at_block: TargetHeaderIdOf<P::MessageLane>, _generated_at_block: TargetHeaderIdOf<MessageLaneAdapter<P>>,
proof: <P::MessageLane as MessageLane>::MessagesReceivingProof, proof: <MessageLaneAdapter<P> as MessageLane>::MessagesReceivingProof,
) -> Result<(), SubstrateError> { ) -> Result<(), SubstrateError> {
let lane = self.lane.clone(); let genesis_hash = *self.client.genesis_hash();
let transaction_params = self.transaction_params.clone();
self.client self.client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.lane.source_transactions_author(), self.transaction_params.signer.public().into(),
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
lane.make_messages_receiving_proof_transaction( make_messages_delivery_proof_transaction::<P>(
&genesis_hash,
&transaction_params,
best_block_id, best_block_id,
transaction_nonce, transaction_nonce,
generated_at_block,
proof, proof,
true,
) )
}, },
) )
@@ -258,7 +248,7 @@ where
Ok(()) Ok(())
} }
async fn require_target_header_on_source(&self, id: TargetHeaderIdOf<P::MessageLane>) { async fn require_target_header_on_source(&self, id: TargetHeaderIdOf<MessageLaneAdapter<P>>) {
if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay {
target_to_source_headers_relay.require_finalized_header(id).await; target_to_source_headers_relay.require_finalized_header(id).await;
} }
@@ -266,13 +256,15 @@ where
async fn estimate_confirmation_transaction( async fn estimate_confirmation_transaction(
&self, &self,
) -> <P::MessageLane as MessageLane>::SourceChainBalance { ) -> <MessageLaneAdapter<P> as MessageLane>::SourceChainBalance {
self.client self.client
.estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( .estimate_extrinsic_fee(make_messages_delivery_proof_transaction::<P>(
self.client.genesis_hash(),
&self.transaction_params,
HeaderId(Default::default(), Default::default()), HeaderId(Default::default(), Default::default()),
Zero::zero(), Zero::zero(),
HeaderId(Default::default(), Default::default()),
prepare_dummy_messages_delivery_proof::<P::SourceChain, P::TargetChain>(), prepare_dummy_messages_delivery_proof::<P::SourceChain, P::TargetChain>(),
false,
)) ))
.await .await
.map(|fee| fee.inclusion_fee()) .map(|fee| fee.inclusion_fee())
@@ -280,12 +272,39 @@ where
} }
} }
/// Make messages delivery proof transaction from given proof.
fn make_messages_delivery_proof_transaction<P: SubstrateMessageLane>(
source_genesis_hash: &HashOf<P::SourceChain>,
source_transaction_params: &TransactionParams<AccountKeyPairOf<P::SourceTransactionSignScheme>>,
source_best_block_id: HeaderIdOf<P::SourceChain>,
transaction_nonce: IndexOf<P::SourceChain>,
proof: SubstrateMessagesDeliveryProof<P::TargetChain>,
trace_call: bool,
) -> Bytes
where
P::SourceTransactionSignScheme: TransactionSignScheme<Chain = P::SourceChain>,
{
let call =
P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call(
proof, trace_call,
);
Bytes(
P::SourceTransactionSignScheme::sign_transaction(
*source_genesis_hash,
&source_transaction_params.signer,
TransactionEra::new(source_best_block_id, source_transaction_params.mortality),
UnsignedTransaction::new(call, transaction_nonce),
)
.encode(),
)
}
/// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction.
/// ///
/// We don't care about proof actually being the valid proof, because its validity doesn't /// We don't care about proof actually being the valid proof, because its validity doesn't
/// affect the call weight - we only care about its size. /// affect the call weight - we only care about its size.
fn prepare_dummy_messages_delivery_proof<SC: Chain, TC: Chain>( fn prepare_dummy_messages_delivery_proof<SC: Chain, TC: Chain>(
) -> SubstrateMessagesReceivingProof<TC> { ) -> SubstrateMessagesDeliveryProof<TC> {
let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint(
SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
1, 1,
@@ -19,14 +19,15 @@
//! <BridgedName> chain. //! <BridgedName> chain.
use crate::{ use crate::{
messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}, messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane},
messages_metrics::StandaloneMessagesMetrics,
messages_source::{read_client_state, SubstrateMessagesProof}, messages_source::{read_client_state, SubstrateMessagesProof},
on_demand_headers::OnDemandHeadersRelay, on_demand_headers::OnDemandHeadersRelay,
TransactionParams,
}; };
use async_trait::async_trait; use async_trait::async_trait;
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState};
use bridge_runtime_common::messages::{ use bridge_runtime_common::messages::{
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
}; };
@@ -38,23 +39,25 @@ use messages_relay::{
}; };
use num_traits::{Bounded, Zero}; use num_traits::{Bounded, Zero};
use relay_substrate_client::{ use relay_substrate_client::{
BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client,
WeightToFeeOf, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme,
UnsignedTransaction, WeightToFeeOf,
}; };
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use relay_utils::{relay_loop::Client as RelayClient, HeaderId};
use sp_core::Bytes; use sp_core::{Bytes, Pair};
use sp_runtime::{traits::Saturating, DeserializeOwned, FixedPointNumber, FixedU128}; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128};
use std::{convert::TryFrom, ops::RangeInclusive}; use std::{convert::TryFrom, ops::RangeInclusive};
/// Message receiving proof returned by the target Substrate node. /// Message receiving proof returned by the target Substrate node.
pub type SubstrateMessagesReceivingProof<C> = pub type SubstrateMessagesDeliveryProof<C> =
(UnrewardedRelayersState, FromBridgedChainMessagesDeliveryProof<HashOf<C>>); (UnrewardedRelayersState, FromBridgedChainMessagesDeliveryProof<HashOf<C>>);
/// Substrate client as Substrate messages target. /// Substrate client as Substrate messages target.
pub struct SubstrateMessagesTarget<P: SubstrateMessageLane> { pub struct SubstrateMessagesTarget<P: SubstrateMessageLane> {
client: Client<P::TargetChain>, client: Client<P::TargetChain>,
lane: P,
lane_id: LaneId, lane_id: LaneId,
relayer_id_at_source: AccountIdOf<P::SourceChain>,
transaction_params: TransactionParams<AccountKeyPairOf<P::TargetTransactionSignScheme>>,
metric_values: StandaloneMessagesMetrics<P::SourceChain, P::TargetChain>, metric_values: StandaloneMessagesMetrics<P::SourceChain, P::TargetChain>,
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>, source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
} }
@@ -63,15 +66,17 @@ impl<P: SubstrateMessageLane> SubstrateMessagesTarget<P> {
/// Create new Substrate headers target. /// Create new Substrate headers target.
pub fn new( pub fn new(
client: Client<P::TargetChain>, client: Client<P::TargetChain>,
lane: P,
lane_id: LaneId, lane_id: LaneId,
relayer_id_at_source: AccountIdOf<P::SourceChain>,
transaction_params: TransactionParams<AccountKeyPairOf<P::TargetTransactionSignScheme>>,
metric_values: StandaloneMessagesMetrics<P::SourceChain, P::TargetChain>, metric_values: StandaloneMessagesMetrics<P::SourceChain, P::TargetChain>,
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>, source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
) -> Self { ) -> Self {
SubstrateMessagesTarget { SubstrateMessagesTarget {
client, client,
lane,
lane_id, lane_id,
relayer_id_at_source,
transaction_params,
metric_values, metric_values,
source_to_target_headers_relay, source_to_target_headers_relay,
} }
@@ -82,8 +87,9 @@ impl<P: SubstrateMessageLane> Clone for SubstrateMessagesTarget<P> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
client: self.client.clone(), client: self.client.clone(),
lane: self.lane.clone(),
lane_id: self.lane_id, lane_id: self.lane_id,
relayer_id_at_source: self.relayer_id_at_source.clone(),
transaction_params: self.transaction_params.clone(),
metric_values: self.metric_values.clone(), metric_values: self.metric_values.clone(),
source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(),
} }
@@ -100,52 +106,34 @@ impl<P: SubstrateMessageLane> RelayClient for SubstrateMessagesTarget<P> {
} }
#[async_trait] #[async_trait]
impl<P> TargetClient<P::MessageLane> for SubstrateMessagesTarget<P> impl<P: SubstrateMessageLane> TargetClient<MessageLaneAdapter<P>> for SubstrateMessagesTarget<P>
where where
P: SubstrateMessageLane, AccountIdOf<P::TargetChain>:
P::SourceChain: Chain< From<<AccountKeyPairOf<P::TargetTransactionSignScheme> as Pair>::Public>,
Hash = <P::MessageLane as MessageLane>::SourceHeaderHash, P::TargetTransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
BlockNumber = <P::MessageLane as MessageLane>::SourceHeaderNumber, BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>>,
Balance = <P::MessageLane as MessageLane>::SourceChainBalance,
>,
BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>> + Bounded,
P::TargetChain: Chain<
Hash = <P::MessageLane as MessageLane>::TargetHeaderHash,
BlockNumber = <P::MessageLane as MessageLane>::TargetHeaderNumber,
>,
IndexOf<P::TargetChain>: DeserializeOwned,
HashOf<P::TargetChain>: Copy,
BlockNumberOf<P::TargetChain>: Copy,
HeaderOf<P::TargetChain>: DeserializeOwned,
BlockNumberOf<P::TargetChain>: BlockNumberBase,
P::MessageLane: MessageLane<
MessagesProof = SubstrateMessagesProof<P::SourceChain>,
MessagesReceivingProof = SubstrateMessagesReceivingProof<P::TargetChain>,
>,
<P::MessageLane as MessageLane>::SourceHeaderNumber: Decode,
<P::MessageLane as MessageLane>::SourceHeaderHash: Decode,
{ {
async fn state(&self) -> Result<TargetClientState<P::MessageLane>, SubstrateError> { async fn state(&self) -> Result<TargetClientState<MessageLaneAdapter<P>>, SubstrateError> {
// we can't continue to deliver messages if target node is out of sync, because // we can't continue to deliver messages if target node is out of sync, because
// it may have already received (some of) messages that we're going to deliver // it may have already received (some of) messages that we're going to deliver
self.client.ensure_synced().await?; self.client.ensure_synced().await?;
read_client_state::< read_client_state::<
_, _,
<P::MessageLane as MessageLane>::SourceHeaderHash, <MessageLaneAdapter<P> as MessageLane>::SourceHeaderHash,
<P::MessageLane as MessageLane>::SourceHeaderNumber, <MessageLaneAdapter<P> as MessageLane>::SourceHeaderNumber,
>(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) >(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD)
.await .await
} }
async fn latest_received_nonce( async fn latest_received_nonce(
&self, &self,
id: TargetHeaderIdOf<P::MessageLane>, id: TargetHeaderIdOf<MessageLaneAdapter<P>>,
) -> Result<(TargetHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> { ) -> Result<(TargetHeaderIdOf<MessageLaneAdapter<P>>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
P::INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), P::SourceChain::FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(),
Bytes(self.lane_id.encode()), Bytes(self.lane_id.encode()),
Some(id.1), Some(id.1),
) )
@@ -157,12 +145,12 @@ where
async fn latest_confirmed_received_nonce( async fn latest_confirmed_received_nonce(
&self, &self,
id: TargetHeaderIdOf<P::MessageLane>, id: TargetHeaderIdOf<MessageLaneAdapter<P>>,
) -> Result<(TargetHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> { ) -> Result<(TargetHeaderIdOf<MessageLaneAdapter<P>>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
P::INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD.into(), P::SourceChain::FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD.into(),
Bytes(self.lane_id.encode()), Bytes(self.lane_id.encode()),
Some(id.1), Some(id.1),
) )
@@ -174,12 +162,13 @@ where
async fn unrewarded_relayers_state( async fn unrewarded_relayers_state(
&self, &self,
id: TargetHeaderIdOf<P::MessageLane>, id: TargetHeaderIdOf<MessageLaneAdapter<P>>,
) -> Result<(TargetHeaderIdOf<P::MessageLane>, UnrewardedRelayersState), SubstrateError> { ) -> Result<(TargetHeaderIdOf<MessageLaneAdapter<P>>, UnrewardedRelayersState), SubstrateError>
{
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
P::INBOUND_LANE_UNREWARDED_RELAYERS_STATE.into(), P::SourceChain::FROM_CHAIN_UNREWARDED_RELAYERS_STATE.into(),
Bytes(self.lane_id.encode()), Bytes(self.lane_id.encode()),
Some(id.1), Some(id.1),
) )
@@ -192,14 +181,17 @@ where
async fn prove_messages_receiving( async fn prove_messages_receiving(
&self, &self,
id: TargetHeaderIdOf<P::MessageLane>, id: TargetHeaderIdOf<MessageLaneAdapter<P>>,
) -> Result< ) -> Result<
(TargetHeaderIdOf<P::MessageLane>, <P::MessageLane as MessageLane>::MessagesReceivingProof), (
TargetHeaderIdOf<MessageLaneAdapter<P>>,
<MessageLaneAdapter<P> as MessageLane>::MessagesReceivingProof,
),
SubstrateError, SubstrateError,
> { > {
let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; let (id, relayers_state) = self.unrewarded_relayers_state(id).await?;
let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key( let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key(
P::MESSAGE_PALLET_NAME_AT_TARGET, P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME,
&self.lane_id, &self.lane_id,
); );
let proof = self let proof = self
@@ -218,22 +210,27 @@ where
async fn submit_messages_proof( async fn submit_messages_proof(
&self, &self,
generated_at_header: SourceHeaderIdOf<P::MessageLane>, _generated_at_header: SourceHeaderIdOf<MessageLaneAdapter<P>>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
proof: <P::MessageLane as MessageLane>::MessagesProof, proof: <MessageLaneAdapter<P> as MessageLane>::MessagesProof,
) -> Result<RangeInclusive<MessageNonce>, SubstrateError> { ) -> Result<RangeInclusive<MessageNonce>, SubstrateError> {
let lane = self.lane.clone(); let genesis_hash = *self.client.genesis_hash();
let transaction_params = self.transaction_params.clone();
let relayer_id_at_source = self.relayer_id_at_source.clone();
let nonces_clone = nonces.clone(); let nonces_clone = nonces.clone();
self.client self.client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.lane.target_transactions_author(), self.transaction_params.signer.public().into(),
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
lane.make_messages_delivery_transaction( make_messages_delivery_transaction::<P>(
&genesis_hash,
&transaction_params,
best_block_id, best_block_id,
transaction_nonce, transaction_nonce,
generated_at_header, relayer_id_at_source,
nonces_clone, nonces_clone,
proof, proof,
true,
) )
}, },
) )
@@ -241,7 +238,7 @@ where
Ok(nonces) Ok(nonces)
} }
async fn require_source_header_on_target(&self, id: SourceHeaderIdOf<P::MessageLane>) { async fn require_source_header_on_target(&self, id: SourceHeaderIdOf<MessageLaneAdapter<P>>) {
if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay {
source_to_target_headers_relay.require_finalized_header(id).await; source_to_target_headers_relay.require_finalized_header(id).await;
} }
@@ -253,7 +250,7 @@ where
total_prepaid_nonces: MessageNonce, total_prepaid_nonces: MessageNonce,
total_dispatch_weight: Weight, total_dispatch_weight: Weight,
total_size: u32, total_size: u32,
) -> Result<<P::MessageLane as MessageLane>::SourceChainBalance, SubstrateError> { ) -> Result<<MessageLaneAdapter<P> as MessageLane>::SourceChainBalance, SubstrateError> {
let conversion_rate = let conversion_rate =
self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| { self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| {
SubstrateError::Custom(format!( SubstrateError::Custom(format!(
@@ -264,16 +261,19 @@ where
})?; })?;
// Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight.
let delivery_tx = self.lane.make_messages_delivery_transaction( let delivery_tx = make_messages_delivery_transaction::<P>(
self.client.genesis_hash(),
&self.transaction_params,
HeaderId(Default::default(), Default::default()), HeaderId(Default::default(), Default::default()),
Zero::zero(), Zero::zero(),
HeaderId(Default::default(), Default::default()), Default::default(),
nonces.clone(), nonces.clone(),
prepare_dummy_messages_proof::<P::SourceChain>( prepare_dummy_messages_proof::<P::SourceChain>(
nonces.clone(), nonces.clone(),
total_dispatch_weight, total_dispatch_weight,
total_size, total_size,
), ),
false,
); );
let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?;
let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee();
@@ -300,20 +300,23 @@ where
let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE);
let larger_delivery_tx_fee = self let larger_delivery_tx_fee = self
.client .client
.estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( .estimate_extrinsic_fee(make_messages_delivery_transaction::<P>(
self.client.genesis_hash(),
&self.transaction_params,
HeaderId(Default::default(), Default::default()), HeaderId(Default::default(), Default::default()),
Zero::zero(), Zero::zero(),
HeaderId(Default::default(), Default::default()), Default::default(),
nonces.clone(), nonces.clone(),
prepare_dummy_messages_proof::<P::SourceChain>( prepare_dummy_messages_proof::<P::SourceChain>(
nonces.clone(), nonces.clone(),
larger_dispatch_weight, larger_dispatch_weight,
total_size, total_size,
), ),
false,
)) ))
.await?; .await?;
compute_prepaid_messages_refund::<P>( compute_prepaid_messages_refund::<P::TargetChain>(
total_prepaid_nonces, total_prepaid_nonces,
compute_fee_multiplier::<P::TargetChain>( compute_fee_multiplier::<P::TargetChain>(
delivery_tx_fee.adjusted_weight_fee, delivery_tx_fee.adjusted_weight_fee,
@@ -359,6 +362,41 @@ where
} }
} }
/// Make messages delivery transaction from given proof.
#[allow(clippy::too_many_arguments)]
fn make_messages_delivery_transaction<P: SubstrateMessageLane>(
target_genesis_hash: &HashOf<P::TargetChain>,
target_transaction_params: &TransactionParams<AccountKeyPairOf<P::TargetTransactionSignScheme>>,
target_best_block_id: HeaderIdOf<P::TargetChain>,
transaction_nonce: IndexOf<P::TargetChain>,
relayer_id_at_source: AccountIdOf<P::SourceChain>,
nonces: RangeInclusive<MessageNonce>,
proof: SubstrateMessagesProof<P::SourceChain>,
trace_call: bool,
) -> Bytes
where
P::TargetTransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
{
let messages_count = nonces.end() - nonces.start() + 1;
let dispatch_weight = proof.0;
let call = P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call(
relayer_id_at_source,
proof,
messages_count as _,
dispatch_weight,
trace_call,
);
Bytes(
P::TargetTransactionSignScheme::sign_transaction(
*target_genesis_hash,
&target_transaction_params.signer,
TransactionEra::new(target_best_block_id, target_transaction_params.mortality),
UnsignedTransaction::new(call, transaction_nonce),
)
.encode(),
)
}
/// Prepare 'dummy' messages proof that will compose the delivery transaction. /// Prepare 'dummy' messages proof that will compose the delivery transaction.
/// ///
/// We don't care about proof actually being the valid proof, because its validity doesn't /// We don't care about proof actually being the valid proof, because its validity doesn't
@@ -425,80 +463,20 @@ fn compute_fee_multiplier<C: Chain>(
/// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces` /// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces`
/// messages has been paid at the source chain. /// messages has been paid at the source chain.
fn compute_prepaid_messages_refund<P: SubstrateMessageLane>( fn compute_prepaid_messages_refund<C: ChainWithMessages>(
total_prepaid_nonces: MessageNonce, total_prepaid_nonces: MessageNonce,
fee_multiplier: FixedU128, fee_multiplier: FixedU128,
) -> BalanceOf<P::TargetChain> { ) -> BalanceOf<C> {
fee_multiplier.saturating_mul_int(WeightToFeeOf::<P::TargetChain>::calc( fee_multiplier.saturating_mul_int(WeightToFeeOf::<C>::calc(
&P::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN.saturating_mul(total_prepaid_nonces), &C::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN.saturating_mul(total_prepaid_nonces),
)) ))
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; use relay_rococo_client::Rococo;
use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; use relay_wococo_client::Wococo;
#[derive(Clone)]
struct TestSubstrateMessageLane;
impl SubstrateMessageLane for TestSubstrateMessageLane {
type MessageLane = crate::messages_lane::SubstrateMessageLaneToSubstrate<
Rococo,
RococoSigningParams,
Wococo,
WococoSigningParams,
>;
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = "";
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = "";
const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = "";
const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = "";
const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = "";
const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = "";
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = "";
const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = "";
const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = "";
const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = "";
const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = 100_000;
type SourceChain = Rococo;
type TargetChain = Wococo;
fn source_transactions_author(&self) -> bp_rococo::AccountId {
unreachable!()
}
fn make_messages_receiving_proof_transaction(
&self,
_best_block_id: SourceHeaderIdOf<Self::MessageLane>,
_transaction_nonce: IndexOf<Rococo>,
_generated_at_block: TargetHeaderIdOf<Self::MessageLane>,
_proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes {
unreachable!()
}
fn target_transactions_author(&self) -> bp_wococo::AccountId {
unreachable!()
}
fn make_messages_delivery_transaction(
&self,
_best_block_id: TargetHeaderIdOf<Self::MessageLane>,
_transaction_nonce: IndexOf<Wococo>,
_generated_at_header: SourceHeaderIdOf<Self::MessageLane>,
_nonces: RangeInclusive<MessageNonce>,
_proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes {
unreachable!()
}
}
#[test] #[test]
fn prepare_dummy_messages_proof_works() { fn prepare_dummy_messages_proof_works() {
@@ -556,11 +534,10 @@ mod tests {
#[test] #[test]
fn compute_prepaid_messages_refund_returns_sane_results() { fn compute_prepaid_messages_refund_returns_sane_results() {
assert!( assert!(
compute_prepaid_messages_refund::<TestSubstrateMessageLane>( compute_prepaid_messages_refund::<Wococo>(
10, 10,
FixedU128::saturating_from_rational(110, 100), FixedU128::saturating_from_rational(110, 100),
) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN) ) > (10 * Wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into()
.into()
); );
} }
} }
@@ -30,12 +30,10 @@ use relay_utils::{
}; };
use crate::{ use crate::{
finality_pipeline::{ finality_pipeline::{SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT},
SubstrateFinalitySyncPipeline, TransactionParams, RECENT_FINALITY_PROOFS_LIMIT,
},
finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource},
finality_target::SubstrateFinalityTarget, finality_target::SubstrateFinalityTarget,
STALL_TIMEOUT, TransactionParams, STALL_TIMEOUT,
}; };
/// On-demand Substrate <-> Substrate headers relay. /// On-demand Substrate <-> Substrate headers relay.
@@ -116,7 +114,7 @@ async fn background_task<P: SubstrateFinalitySyncPipeline>(
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>, P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
{ {
let relay_task_name = on_demand_headers_relay_name::<P::SourceChain, P::TargetChain>(); let relay_task_name = on_demand_headers_relay_name::<P::SourceChain, P::TargetChain>();
let target_transactions_mortality = target_transaction_params.transactions_mortality; let target_transactions_mortality = target_transaction_params.mortality;
let mut finality_source = SubstrateFinalitySource::<P>::new( let mut finality_source = SubstrateFinalitySource::<P>::new(
source_client.clone(), source_client.clone(),
Some(required_header_number.clone()), Some(required_header_number.clone()),