mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-25 21:07:56 +00:00
Generate large messages (#700)
* generate large messages * consider headers sync lag when computing number of rewards in confirmation * more fixes * fix logs * fix warnings * do not wait until tx that has delivered nonces will be finalized before submitting other tx * tests for maximal weight/size * cleanup * cleanup * clippy * compilation * args for dispatch weight and remark size * ExplicitOrMaximal * clippy
This commit is contained in:
committed by
Bastian Köcher
parent
3dfef2cd2c
commit
1b2e6cdeb0
@@ -17,6 +17,7 @@
|
||||
//! Deal with CLI args of substrate-to-substrate relay.
|
||||
|
||||
use bp_message_lane::LaneId;
|
||||
use frame_support::weights::Weight;
|
||||
use sp_core::Bytes;
|
||||
use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId;
|
||||
use structopt::{clap::arg_enum, StructOpt};
|
||||
@@ -153,6 +154,9 @@ pub enum SendMessage {
|
||||
/// Hex-encoded lane id.
|
||||
#[structopt(long)]
|
||||
lane: HexLaneId,
|
||||
/// Dispatch weight of the message. If not passed, determined automatically.
|
||||
#[structopt(long)]
|
||||
dispatch_weight: Option<ExplicitOrMaximal<Weight>>,
|
||||
/// Delivery and dispatch fee. If not passed, determined automatically.
|
||||
#[structopt(long)]
|
||||
fee: Option<bp_millau::Balance>,
|
||||
@@ -174,6 +178,9 @@ pub enum SendMessage {
|
||||
/// Hex-encoded lane id.
|
||||
#[structopt(long)]
|
||||
lane: HexLaneId,
|
||||
/// Dispatch weight of the message. If not passed, determined automatically.
|
||||
#[structopt(long)]
|
||||
dispatch_weight: Option<ExplicitOrMaximal<Weight>>,
|
||||
/// Delivery and dispatch fee. If not passed, determined automatically.
|
||||
#[structopt(long)]
|
||||
fee: Option<bp_rialto::Balance>,
|
||||
@@ -190,7 +197,11 @@ pub enum SendMessage {
|
||||
#[derive(StructOpt, Debug)]
|
||||
pub enum ToRialtoMessage {
|
||||
/// Make an on-chain remark (comment).
|
||||
Remark,
|
||||
Remark {
|
||||
/// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark.
|
||||
#[structopt(long)]
|
||||
remark_size: Option<ExplicitOrMaximal<usize>>,
|
||||
},
|
||||
/// Transfer the specified `amount` of native tokens to a particular `recipient`.
|
||||
Transfer {
|
||||
#[structopt(long)]
|
||||
@@ -204,7 +215,11 @@ pub enum ToRialtoMessage {
|
||||
#[derive(StructOpt, Debug)]
|
||||
pub enum ToMillauMessage {
|
||||
/// Make an on-chain remark (comment).
|
||||
Remark,
|
||||
Remark {
|
||||
/// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark.
|
||||
#[structopt(long)]
|
||||
remark_size: Option<ExplicitOrMaximal<usize>>,
|
||||
},
|
||||
/// Transfer the specified `amount` of native tokens to a particular `recipient`.
|
||||
Transfer {
|
||||
#[structopt(long)]
|
||||
@@ -273,6 +288,32 @@ impl From<PrometheusParams> for Option<relay_utils::metrics::MetricsParams> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Either explicit or maximal allowed value.
|
||||
#[derive(Debug)]
|
||||
pub enum ExplicitOrMaximal<V> {
|
||||
/// User has explicitly specified argument value.
|
||||
Explicit(V),
|
||||
/// Maximal allowed value for this argument.
|
||||
Maximal,
|
||||
}
|
||||
|
||||
impl<V: std::str::FromStr> std::str::FromStr for ExplicitOrMaximal<V>
|
||||
where
|
||||
V::Err: std::fmt::Debug,
|
||||
{
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.to_lowercase() == "max" {
|
||||
return Ok(ExplicitOrMaximal::Maximal);
|
||||
}
|
||||
|
||||
V::from_str(s)
|
||||
.map(ExplicitOrMaximal::Explicit)
|
||||
.map_err(|e| format!("Failed to parse '{:?}'. Expected 'max' or explicit value", e))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_chain_options {
|
||||
($chain:ident, $chain_prefix:ident) => {
|
||||
paste::item! {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::weights::GetDispatchInfo;
|
||||
use frame_support::weights::{GetDispatchInfo, Weight};
|
||||
use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload};
|
||||
use relay_kusama_client::Kusama;
|
||||
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
|
||||
@@ -232,6 +232,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
rialto_sign,
|
||||
lane,
|
||||
message,
|
||||
dispatch_weight,
|
||||
fee,
|
||||
origin,
|
||||
..
|
||||
@@ -241,7 +242,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
let rialto_sign = rialto_sign.parse()?;
|
||||
let rialto_call = message.into_call();
|
||||
|
||||
let payload = millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin);
|
||||
let payload =
|
||||
millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin, dispatch_weight);
|
||||
let dispatch_weight = payload.weight;
|
||||
|
||||
let lane = lane.into();
|
||||
let fee = get_fee(fee, || {
|
||||
@@ -254,8 +257,6 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
})
|
||||
.await?;
|
||||
|
||||
log::info!(target: "bridge", "Sending message to Rialto. Fee: {}", fee);
|
||||
|
||||
let millau_call = millau_runtime::Call::BridgeRialtoMessageLane(
|
||||
millau_runtime::MessageLaneCall::send_message(lane, payload, fee),
|
||||
);
|
||||
@@ -267,11 +268,18 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
.next_account_index(millau_sign.signer.public().clone().into())
|
||||
.await?,
|
||||
millau_call,
|
||||
)
|
||||
.encode();
|
||||
|
||||
log::info!(
|
||||
target: "bridge",
|
||||
"Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}",
|
||||
signed_millau_call.len(),
|
||||
dispatch_weight,
|
||||
fee,
|
||||
);
|
||||
|
||||
millau_client
|
||||
.submit_extrinsic(Bytes(signed_millau_call.encode()))
|
||||
.await?;
|
||||
millau_client.submit_extrinsic(Bytes(signed_millau_call)).await?;
|
||||
}
|
||||
cli::SendMessage::RialtoToMillau {
|
||||
rialto,
|
||||
@@ -279,6 +287,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
millau_sign,
|
||||
lane,
|
||||
message,
|
||||
dispatch_weight,
|
||||
fee,
|
||||
origin,
|
||||
..
|
||||
@@ -288,7 +297,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
let millau_sign = millau_sign.parse()?;
|
||||
let millau_call = message.into_call();
|
||||
|
||||
let payload = rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin);
|
||||
let payload =
|
||||
rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin, dispatch_weight);
|
||||
let dispatch_weight = payload.weight;
|
||||
|
||||
let lane = lane.into();
|
||||
let fee = get_fee(fee, || {
|
||||
@@ -301,8 +312,6 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
})
|
||||
.await?;
|
||||
|
||||
log::info!(target: "bridge", "Sending message to Millau. Fee: {}", fee);
|
||||
|
||||
let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane(
|
||||
rialto_runtime::MessageLaneCall::send_message(lane, payload, fee),
|
||||
);
|
||||
@@ -314,11 +323,18 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> {
|
||||
.next_account_index(rialto_sign.signer.public().clone().into())
|
||||
.await?,
|
||||
rialto_call,
|
||||
)
|
||||
.encode();
|
||||
|
||||
log::info!(
|
||||
target: "bridge",
|
||||
"Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}",
|
||||
signed_rialto_call.len(),
|
||||
dispatch_weight,
|
||||
fee,
|
||||
);
|
||||
|
||||
rialto_client
|
||||
.submit_extrinsic(Bytes(signed_rialto_call.encode()))
|
||||
.await?;
|
||||
rialto_client.submit_extrinsic(Bytes(signed_rialto_call)).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -338,16 +354,20 @@ async fn estimate_message_delivery_and_dispatch_fee<Fee: Decode, C: Chain, P: En
|
||||
Ok(decoded_response)
|
||||
}
|
||||
|
||||
fn remark_payload() -> Vec<u8> {
|
||||
format!(
|
||||
"Unix time: {}",
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs(),
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
fn remark_payload(remark_size: Option<cli::ExplicitOrMaximal<usize>>, maximal_allowed_size: u32) -> Vec<u8> {
|
||||
match remark_size {
|
||||
Some(cli::ExplicitOrMaximal::Explicit(remark_size)) => vec![0; remark_size],
|
||||
Some(cli::ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _],
|
||||
None => format!(
|
||||
"Unix time: {}",
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs(),
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn rialto_to_millau_message_payload(
|
||||
@@ -355,8 +375,13 @@ fn rialto_to_millau_message_payload(
|
||||
millau_sign: &MillauSigningParams,
|
||||
millau_call: &millau_runtime::Call,
|
||||
origin: cli::Origins,
|
||||
user_specified_dispatch_weight: Option<cli::ExplicitOrMaximal<Weight>>,
|
||||
) -> rialto_runtime::millau_messages::ToMillauMessagePayload {
|
||||
let millau_call_weight = millau_call.get_dispatch_info().weight;
|
||||
let millau_call_weight = prepare_call_dispatch_weight(
|
||||
user_specified_dispatch_weight,
|
||||
cli::ExplicitOrMaximal::Explicit(millau_call.get_dispatch_info().weight),
|
||||
compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()),
|
||||
);
|
||||
let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into();
|
||||
let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account();
|
||||
let millau_origin_public = millau_sign.signer.public();
|
||||
@@ -387,8 +412,13 @@ fn millau_to_rialto_message_payload(
|
||||
rialto_sign: &RialtoSigningParams,
|
||||
rialto_call: &rialto_runtime::Call,
|
||||
origin: cli::Origins,
|
||||
user_specified_dispatch_weight: Option<cli::ExplicitOrMaximal<Weight>>,
|
||||
) -> millau_runtime::rialto_messages::ToRialtoMessagePayload {
|
||||
let rialto_call_weight = rialto_call.get_dispatch_info().weight;
|
||||
let rialto_call_weight = prepare_call_dispatch_weight(
|
||||
user_specified_dispatch_weight,
|
||||
cli::ExplicitOrMaximal::Explicit(rialto_call.get_dispatch_info().weight),
|
||||
compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()),
|
||||
);
|
||||
let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into();
|
||||
let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account();
|
||||
let rialto_origin_public = rialto_sign.signer.public();
|
||||
@@ -414,6 +444,17 @@ fn millau_to_rialto_message_payload(
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_call_dispatch_weight(
|
||||
user_specified_dispatch_weight: Option<cli::ExplicitOrMaximal<Weight>>,
|
||||
weight_from_pre_dispatch_call: cli::ExplicitOrMaximal<Weight>,
|
||||
maximal_allowed_weight: Weight,
|
||||
) -> Weight {
|
||||
match user_specified_dispatch_weight.unwrap_or(weight_from_pre_dispatch_call) {
|
||||
cli::ExplicitOrMaximal::Explicit(weight) => weight,
|
||||
cli::ExplicitOrMaximal::Maximal => maximal_allowed_weight,
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_fee<Fee, F, R, E>(fee: Option<Fee>, f: F) -> Result<Fee, String>
|
||||
where
|
||||
Fee: Decode,
|
||||
@@ -431,6 +472,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight {
|
||||
bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight)
|
||||
}
|
||||
|
||||
fn compute_maximal_message_arguments_size(
|
||||
maximal_source_extrinsic_size: u32,
|
||||
maximal_target_extrinsic_size: u32,
|
||||
) -> u32 {
|
||||
// assume that both signed extensions and other arguments fit 1KB
|
||||
let service_tx_bytes_on_source_chain = 1024;
|
||||
let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain;
|
||||
let maximal_call_size =
|
||||
bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size);
|
||||
let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size {
|
||||
maximal_source_extrinsic_size
|
||||
} else {
|
||||
maximal_call_size
|
||||
};
|
||||
|
||||
// bytes in Call encoding that are used to encode everything except arguments
|
||||
let service_bytes = 1 + 1 + 4;
|
||||
maximal_call_size - service_bytes
|
||||
}
|
||||
|
||||
impl crate::cli::RialtoSigningParams {
|
||||
/// Parse CLI parameters into typed signing params.
|
||||
pub fn parse(self) -> Result<RialtoSigningParams, String> {
|
||||
@@ -472,8 +537,14 @@ impl crate::cli::ToRialtoMessage {
|
||||
/// Convert CLI call request into runtime `Call` instance.
|
||||
pub fn into_call(self) -> rialto_runtime::Call {
|
||||
match self {
|
||||
cli::ToRialtoMessage::Remark => {
|
||||
rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload()))
|
||||
cli::ToRialtoMessage::Remark { remark_size } => {
|
||||
rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload(
|
||||
remark_size,
|
||||
compute_maximal_message_arguments_size(
|
||||
bp_millau::max_extrinsic_size(),
|
||||
bp_rialto::max_extrinsic_size(),
|
||||
),
|
||||
)))
|
||||
}
|
||||
cli::ToRialtoMessage::Transfer { recipient, amount } => {
|
||||
rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount))
|
||||
@@ -486,8 +557,14 @@ impl crate::cli::ToMillauMessage {
|
||||
/// Convert CLI call request into runtime `Call` instance.
|
||||
pub fn into_call(self) -> millau_runtime::Call {
|
||||
match self {
|
||||
cli::ToMillauMessage::Remark => {
|
||||
millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload()))
|
||||
cli::ToMillauMessage::Remark { remark_size } => {
|
||||
millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload(
|
||||
remark_size,
|
||||
compute_maximal_message_arguments_size(
|
||||
bp_rialto::max_extrinsic_size(),
|
||||
bp_millau::max_extrinsic_size(),
|
||||
),
|
||||
)))
|
||||
}
|
||||
cli::ToMillauMessage::Transfer { recipient, amount } => {
|
||||
millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount))
|
||||
@@ -498,6 +575,8 @@ impl crate::cli::ToMillauMessage {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bp_message_lane::source_chain::TargetHeaderChain;
|
||||
use sp_core::Pair;
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
@@ -542,4 +621,89 @@ mod tests {
|
||||
|
||||
assert!(signature.verify(&digest[..], &millau_signer.signer.public()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maximal_rialto_to_millau_message_arguments_size_is_computed_correctly() {
|
||||
use rialto_runtime::millau_messages::Millau;
|
||||
|
||||
let maximal_remark_size =
|
||||
compute_maximal_message_arguments_size(bp_rialto::max_extrinsic_size(), bp_millau::max_extrinsic_size());
|
||||
|
||||
let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into();
|
||||
let payload = pallet_bridge_call_dispatch::MessagePayload {
|
||||
spec_version: Default::default(),
|
||||
weight: call.get_dispatch_info().weight,
|
||||
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||
call: call.encode(),
|
||||
};
|
||||
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
||||
|
||||
let call: millau_runtime::Call =
|
||||
millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into();
|
||||
let payload = pallet_bridge_call_dispatch::MessagePayload {
|
||||
spec_version: Default::default(),
|
||||
weight: call.get_dispatch_info().weight,
|
||||
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||
call: call.encode(),
|
||||
};
|
||||
assert!(Millau::verify_message(&payload).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maximal_size_remark_to_rialto_is_generated_correctly() {
|
||||
assert!(
|
||||
bridge_runtime_common::messages::target::maximal_incoming_message_size(
|
||||
bp_rialto::max_extrinsic_size()
|
||||
) > bp_millau::max_extrinsic_size(),
|
||||
"We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() {
|
||||
use rialto_runtime::millau_messages::Millau;
|
||||
|
||||
let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight());
|
||||
let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into();
|
||||
|
||||
let payload = pallet_bridge_call_dispatch::MessagePayload {
|
||||
spec_version: Default::default(),
|
||||
weight: maximal_dispatch_weight,
|
||||
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||
call: call.encode(),
|
||||
};
|
||||
assert_eq!(Millau::verify_message(&payload), Ok(()));
|
||||
|
||||
let payload = pallet_bridge_call_dispatch::MessagePayload {
|
||||
spec_version: Default::default(),
|
||||
weight: maximal_dispatch_weight + 1,
|
||||
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||
call: call.encode(),
|
||||
};
|
||||
assert!(Millau::verify_message(&payload).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maximal_weight_fill_block_to_rialto_is_generated_correctly() {
|
||||
use millau_runtime::rialto_messages::Rialto;
|
||||
|
||||
let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight());
|
||||
let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into();
|
||||
|
||||
let payload = pallet_bridge_call_dispatch::MessagePayload {
|
||||
spec_version: Default::default(),
|
||||
weight: maximal_dispatch_weight,
|
||||
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||
call: call.encode(),
|
||||
};
|
||||
assert_eq!(Rialto::verify_message(&payload), Ok(()));
|
||||
|
||||
let payload = pallet_bridge_call_dispatch::MessagePayload {
|
||||
spec_version: Default::default(),
|
||||
weight: maximal_dispatch_weight + 1,
|
||||
origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot,
|
||||
call: call.encode(),
|
||||
};
|
||||
assert!(Rialto::verify_message(&payload).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ mod tests {
|
||||
#[test]
|
||||
fn select_delivery_transaction_limits_works() {
|
||||
let (max_count, max_weight) = select_delivery_transaction_limits::<RialtoToMillauMessageLaneWeights>(
|
||||
bp_rialto::max_extrinsic_weight(),
|
||||
bp_millau::max_extrinsic_weight(),
|
||||
bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE,
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -176,7 +176,7 @@ mod tests {
|
||||
// reserved for messages dispatch allows dispatch of non-trivial messages.
|
||||
//
|
||||
// Any significant change in this values should attract additional attention.
|
||||
(1024, 866_583_333_334),
|
||||
(955, 216_583_333_334),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user