mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 19:31:02 +00:00
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:
committed by
Bastian Köcher
parent
90f2b3c365
commit
4cdd959057
@@ -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`
|
||||||
|
|||||||
@@ -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`
|
||||||
|
|||||||
@@ -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`
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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()),
|
||||||
|
|||||||
Reference in New Issue
Block a user