From 4668afb83bf57702df96134eb0a7092a418615b5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 21 Jan 2021 12:35:04 +0300 Subject: [PATCH] Use real weights to compute message delivery and dispatch fee (#598) * message fee formula * update GetDelvieryConfirmationTransactionFee * include cost of transactions (i.e. not only dispatch cost) in delivery_and_dispatch_fee * endow relayers fund account * include db ops weight in max tx weight estimation * (in bytes) Co-authored-by: Hernando Castano --- bridges/bin/millau/node/Cargo.toml | 1 + bridges/bin/millau/node/src/chain_spec.rs | 1 + bridges/bin/millau/runtime/src/lib.rs | 19 ++++++- .../bin/millau/runtime/src/rialto_messages.rs | 32 +++++++---- bridges/bin/rialto/node/Cargo.toml | 1 + bridges/bin/rialto/node/src/chain_spec.rs | 1 + bridges/bin/rialto/runtime/src/lib.rs | 12 +++-- .../bin/rialto/runtime/src/millau_messages.rs | 32 +++++++---- bridges/bin/runtime-common/src/messages.rs | 54 +++++++++++-------- bridges/modules/message-lane/rpc/Cargo.toml | 1 + bridges/modules/message-lane/rpc/src/lib.rs | 17 +++++- bridges/modules/message-lane/src/lib.rs | 7 ++- .../modules/message-lane/src/weights_ext.rs | 29 +++++++++- bridges/primitives/message-lane/src/lib.rs | 34 ++++++++++++ bridges/primitives/millau/src/lib.rs | 38 +++++++++++++ bridges/primitives/rialto/src/lib.rs | 38 +++++++++++++ 16 files changed, 265 insertions(+), 52 deletions(-) diff --git a/bridges/bin/millau/node/Cargo.toml b/bridges/bin/millau/node/Cargo.toml index 34044c2766305..83ff05f7049cf 100644 --- a/bridges/bin/millau/node/Cargo.toml +++ b/bridges/bin/millau/node/Cargo.toml @@ -19,6 +19,7 @@ bp-message-lane = { path = "../../../primitives/message-lane" } bp-millau= { path = "../../../primitives/millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } +pallet-message-lane = { path = "../../../modules/message-lane" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } # Substrate Dependencies diff --git a/bridges/bin/millau/node/src/chain_spec.rs b/bridges/bin/millau/node/src/chain_spec.rs index 2ead8612fac21..bf1dce3ae5594 100644 --- a/bridges/bin/millau/node/src/chain_spec.rs +++ b/bridges/bin/millau/node/src/chain_spec.rs @@ -122,6 +122,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + pallet_message_lane::Module::::relayer_fund_account_id(), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 0e56f24d66085..e79b34d2790ef 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -315,8 +315,9 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; - // TODO: https://github.com/paritytech/parity-bridges-common/pull/598 - pub GetDeliveryConfirmationTransactionFee: Balance = 0; + // `IdentityFee` is used by Millau => we may use weight directly + pub const GetDeliveryConfirmationTransactionFee: Balance = + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; } @@ -594,3 +595,17 @@ impl_runtime_apis! { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ensure_millau_message_lane_weights_are_correct() { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 + pallet_message_lane::ensure_weights_are_correct::>( + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ); + } +} diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index 5129276d04f9b..9f2144b5636d5 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -26,7 +26,7 @@ use bp_message_lane::{ use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ - weights::{Weight, WeightToFeePolynomial}, + weights::{DispatchClass, Weight, WeightToFeePolynomial}, RuntimeDebug, }; use sp_core::storage::StorageKey; @@ -98,21 +98,35 @@ impl MessageBridge for WithRialtoMessageBridge { // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() - let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + let lower_limit = u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX); lower_limit..=upper_limit } - fn weight_of_delivery_transaction() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX) + .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + ) } fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 - } - - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + let inbounded_data_size: Weight = + InboundLaneData::::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) + .map(Into::into) + .unwrap_or(Weight::MAX); + + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + inbounded_data_size.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ) } fn this_weight_to_this_balance(weight: Weight) -> bp_millau::Balance { diff --git a/bridges/bin/rialto/node/Cargo.toml b/bridges/bin/rialto/node/Cargo.toml index c2620ab9e3cec..aade85879c551 100644 --- a/bridges/bin/rialto/node/Cargo.toml +++ b/bridges/bin/rialto/node/Cargo.toml @@ -18,6 +18,7 @@ structopt = "0.3.21" bp-message-lane = { path = "../../../primitives/message-lane" } bp-runtime = { path = "../../../primitives/runtime" } bp-rialto = { path = "../../../primitives/rialto" } +pallet-message-lane = { path = "../../../modules/message-lane" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } rialto-runtime = { path = "../runtime" } diff --git a/bridges/bin/rialto/node/src/chain_spec.rs b/bridges/bin/rialto/node/src/chain_spec.rs index dc2a9afea6135..cf90802239569 100644 --- a/bridges/bin/rialto/node/src/chain_spec.rs +++ b/bridges/bin/rialto/node/src/chain_spec.rs @@ -122,6 +122,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + pallet_message_lane::Module::::relayer_fund_account_id(), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index a77d590612609..060784ab3ec56 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -419,11 +419,12 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_message_lane::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; - // TODO: https://github.com/paritytech/parity-bridges-common/pull/598 - pub GetDeliveryConfirmationTransactionFee: Balance = 0; + // `IdentityFee` is used by Rialto => we may use weight directly + pub const GetDeliveryConfirmationTransactionFee: Balance = + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; } @@ -1026,7 +1027,10 @@ mod tests { #[test] fn ensure_rialto_message_lane_weights_are_correct() { - pallet_message_lane::ensure_weights_are_correct::>(); + pallet_message_lane::ensure_weights_are_correct::>( + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ); } #[test] diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index 173bde8cad6e8..61a8682d12754 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -26,7 +26,7 @@ use bp_message_lane::{ use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ - weights::{Weight, WeightToFeePolynomial}, + weights::{DispatchClass, Weight, WeightToFeePolynomial}, RuntimeDebug, }; use sp_core::storage::StorageKey; @@ -99,21 +99,35 @@ impl MessageBridge for WithMillauMessageBridge { // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() - let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + let lower_limit = u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX); lower_limit..=upper_limit } - fn weight_of_delivery_transaction() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX) + .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + ) } fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 - } - - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + let inbounded_data_size: Weight = + InboundLaneData::::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) + .map(Into::into) + .unwrap_or(Weight::MAX); + + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + inbounded_data_size.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ) } fn this_weight_to_this_balance(weight: Weight) -> bp_rialto::Balance { diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index 897de2af6a224..cd84612d109be 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -28,7 +28,7 @@ use bp_message_lane::{ }; use bp_runtime::InstanceId; use codec::{Compact, Decode, Encode, Input}; -use frame_support::{traits::Instance, RuntimeDebug}; +use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; @@ -65,16 +65,11 @@ pub trait MessageBridge { ) -> RangeInclusive>>; /// Maximal weight of single message delivery transaction on Bridged chain. - fn weight_of_delivery_transaction() -> WeightOf>; + fn weight_of_delivery_transaction(message_payload: &[u8]) -> WeightOf>; /// Maximal weight of single message delivery confirmation transaction on This chain. fn weight_of_delivery_confirmation_transaction_on_this_chain() -> WeightOf>; - /// Weight of single message reward confirmation on the Bridged chain. This confirmation - /// is a part of delivery transaction, so this weight is added to the delivery - /// transaction weight. - fn weight_of_reward_confirmation_transaction_on_target_chain() -> WeightOf>; - /// Convert weight of This chain to the fee (paid in Balance) of This chain. fn this_weight_to_this_balance(weight: WeightOf>) -> BalanceOf>; @@ -120,6 +115,31 @@ pub(crate) type BalanceOf = ::Balance; pub(crate) type CallOf = ::Call; pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; +/// Compute weight of transaction at runtime where: +/// +/// - transaction payment pallet is being used; +/// - fee multiplier is zero. +pub fn transaction_weight_without_multiplier( + base_weight: Weight, + payload_size: Weight, + dispatch_weight: Weight, +) -> Weight { + // non-adjustable per-byte weight is mapped 1:1 to tx weight + let per_byte_weight = payload_size; + + // we assume that adjustable per-byte weight is always zero + let adjusted_per_byte_weight = 0; + + // we assume that transaction tip we use is also zero + let transaction_tip_weight = 0; + + base_weight + .saturating_add(per_byte_weight) + .saturating_add(adjusted_per_byte_weight) + .saturating_add(transaction_tip_weight) + .saturating_add(dispatch_weight) +} + /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -226,10 +246,8 @@ pub mod source { relayer_fee_percent: u32, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction()); + let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction(&payload.call)); let dispatch_fee = B::bridged_weight_to_bridged_balance(payload.weight.into()); - let reward_confirmation_fee = - B::bridged_weight_to_bridged_balance(B::weight_of_reward_confirmation_transaction_on_target_chain()); // the fee (in This tokens) of all transactions that are made on This chain let delivery_confirmation_fee = @@ -238,7 +256,6 @@ pub mod source { // minimal fee (in This tokens) is a sum of all required fees let minimal_fee = delivery_fee .checked_add(&dispatch_fee) - .and_then(|fee| fee.checked_add(&reward_confirmation_fee)) .map(B::bridged_balance_to_this_balance) .and_then(|fee| fee.checked_add(&delivery_confirmation_fee)); @@ -570,7 +587,6 @@ mod tests { const DELIVERY_TRANSACTION_WEIGHT: Weight = 100; const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; - const REWARD_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; @@ -596,7 +612,7 @@ mod tests { begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } - fn weight_of_delivery_transaction() -> Weight { + fn weight_of_delivery_transaction(_message_payload: &[u8]) -> Weight { DELIVERY_TRANSACTION_WEIGHT } @@ -604,10 +620,6 @@ mod tests { DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT } - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - REWARD_CONFIRMATION_TRANSACTION_WEIGHT - } - fn this_weight_to_this_balance(weight: Weight) -> ThisChainBalance { ThisChainBalance(weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } @@ -639,7 +651,7 @@ mod tests { unreachable!() } - fn weight_of_delivery_transaction() -> Weight { + fn weight_of_delivery_transaction(_message_payload: &[u8]) -> Weight { unreachable!() } @@ -647,10 +659,6 @@ mod tests { unreachable!() } - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - unreachable!() - } - fn this_weight_to_this_balance(_weight: Weight) -> BridgedChainBalance { unreachable!() } @@ -809,7 +817,7 @@ mod tests { #[test] fn message_fee_is_checked_by_verifier() { - const EXPECTED_MINIMAL_FEE: u32 = 8140; + const EXPECTED_MINIMAL_FEE: u32 = 5500; // payload of the This -> Bridged chain message let payload = source::FromThisChainMessagePayload:: { diff --git a/bridges/modules/message-lane/rpc/Cargo.toml b/bridges/modules/message-lane/rpc/Cargo.toml index 73111d0d28ec7..28481a7ad8834 100644 --- a/bridges/modules/message-lane/rpc/Cargo.toml +++ b/bridges/modules/message-lane/rpc/Cargo.toml @@ -12,6 +12,7 @@ futures = { version = "0.3.5", features = ["compat"] } jsonrpc-core = "15.1.0" jsonrpc-core-client = "15.1.0" jsonrpc-derive = "15.1.0" +log = "0.4.11" # Bridge dependencies diff --git a/bridges/modules/message-lane/rpc/src/lib.rs b/bridges/modules/message-lane/rpc/src/lib.rs index df85064f3c414..8532ed0c5d0e7 100644 --- a/bridges/modules/message-lane/rpc/src/lib.rs +++ b/bridges/modules/message-lane/rpc/src/lib.rs @@ -116,6 +116,7 @@ where } else { None }; + let messages_count = if end >= begin { end - begin + 1 } else { 0 }; Box::new( prove_keys_read( self.backend.clone(), @@ -126,7 +127,15 @@ where ) .boxed() .compat() - .map(serialize_storage_proof) + .map(move |proof| { + let serialized_proof = serialize_storage_proof(proof); + log::trace!( + "Generated proof of {} messages. Size: {}", + messages_count, + serialized_proof.len() + ); + serialized_proof + }) .map_err(Into::into), ) } @@ -145,7 +154,11 @@ where ) .boxed() .compat() - .map(serialize_storage_proof) + .map(|proof| { + let serialized_proof = serialize_storage_proof(proof); + log::trace!("Generated message delivery proof. Size: {}", serialized_proof.len()); + serialized_proof + }) .map_err(Into::into), ) } diff --git a/bridges/modules/message-lane/src/lib.rs b/bridges/modules/message-lane/src/lib.rs index b6cf818f5bd9c..9c44e7289bfd5 100644 --- a/bridges/modules/message-lane/src/lib.rs +++ b/bridges/modules/message-lane/src/lib.rs @@ -326,16 +326,19 @@ decl_module! { // finally, save message in outbound storage and emit event let mut lane = outbound_lane::(lane_id); + let encoded_payload = payload.encode(); + let encoded_payload_len = encoded_payload.len(); let nonce = lane.send_message(MessageData { - payload: payload.encode(), + payload: encoded_payload, fee: delivery_and_dispatch_fee, }); lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); frame_support::debug::trace!( - "Accepted message {} to lane {:?}", + "Accepted message {} to lane {:?}. Message size: {:?}", nonce, lane_id, + encoded_payload_len, ); Self::deposit_event(RawEvent::MessageAccepted(lane_id, nonce)); diff --git a/bridges/modules/message-lane/src/weights_ext.rs b/bridges/modules/message-lane/src/weights_ext.rs index b9b33a6f21f9e..95bc8239a9463 100644 --- a/bridges/modules/message-lane/src/weights_ext.rs +++ b/bridges/modules/message-lane/src/weights_ext.rs @@ -22,7 +22,10 @@ use bp_message_lane::MessageNonce; use frame_support::weights::Weight; /// Ensure that weights from `WeightInfoExt` implementation are looking correct. -pub fn ensure_weights_are_correct() { +pub fn ensure_weights_are_correct( + expected_max_single_message_delivery_tx_weight: Weight, + expected_max_messages_delivery_tx_weight: Weight, +) { assert_ne!(W::send_message_overhead(), 0); assert_ne!(W::send_message_size_overhead(0), 0); @@ -30,9 +33,33 @@ pub fn ensure_weights_are_correct() { assert_ne!(W::receive_messages_proof_messages_overhead(1), 0); assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), 0); + let actual_max_single_message_delivery_tx_weight = W::receive_messages_proof_overhead() + .checked_add(W::receive_messages_proof_messages_overhead(1)) + .expect("weights are too large") + .checked_add(W::receive_messages_proof_outbound_lane_state_overhead()) + .expect("weights are too large"); + assert!( + actual_max_single_message_delivery_tx_weight <= expected_max_single_message_delivery_tx_weight, + "Single message delivery transaction weight {} is larger than expected weight {}", + actual_max_single_message_delivery_tx_weight, + expected_max_single_message_delivery_tx_weight, + ); + assert_ne!(W::receive_messages_delivery_proof_overhead(), 0); assert_ne!(W::receive_messages_delivery_proof_messages_overhead(1), 0); assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1), 0); + + let actual_max_messages_delivery_tx_weight = W::receive_messages_delivery_proof_overhead() + .checked_add(W::receive_messages_delivery_proof_messages_overhead(1)) + .expect("weights are too large") + .checked_add(W::receive_messages_delivery_proof_relayers_overhead(1)) + .expect("weights are too large"); + assert!( + actual_max_messages_delivery_tx_weight <= expected_max_messages_delivery_tx_weight, + "Messages delivery confirmation transaction weight {} is larger than expected weight {}", + actual_max_messages_delivery_tx_weight, + expected_max_messages_delivery_tx_weight, + ); } /// Extended weight info. diff --git a/bridges/primitives/message-lane/src/lib.rs b/bridges/primitives/message-lane/src/lib.rs index 74086cccce846..47f33970ae111 100644 --- a/bridges/primitives/message-lane/src/lib.rs +++ b/bridges/primitives/message-lane/src/lib.rs @@ -113,6 +113,17 @@ impl Default for InboundLaneData { } impl InboundLaneData { + /// Returns approximate size of the struct, given number of entries in the `relayers` set and + /// size of each entry. + /// + /// Returns `None` if size overflows `u32` limits. + pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32) -> Option { + let message_nonce_size = 8; + let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; + let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; + relayers_size.checked_add(message_nonce_size) + } + /// Nonce of the last message that has been delivered to this (target) chain. pub fn last_delivered_nonce(&self) -> MessageNonce { self.relayers @@ -191,3 +202,26 @@ mod tests { ); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn inbound_lane_data_returns_correct_hint() { + let expected_size = InboundLaneData::::encoded_size_hint(1, 13); + let actual_size = InboundLaneData { + relayers: (1u8..=13u8).map(|i| (i as _, i as _, i)).collect(), + last_confirmed_nonce: 13, + } + .encode() + .len(); + let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs(); + assert!( + difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1, + "Too large difference between actual ({}) and expected ({:?}) inbound lane data size", + actual_size, + expected_size, + ); + } +} diff --git a/bridges/primitives/millau/src/lib.rs b/bridges/primitives/millau/src/lib.rs index 636697847cd40..5c0febdca399a 100644 --- a/bridges/primitives/millau/src/lib.rs +++ b/bridges/primitives/millau/src/lib.rs @@ -43,6 +43,14 @@ use serde::{Deserialize, Serialize}; pub use millau_hash::MillauHash; +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// Millau chain. This mostly depends on number of entries (and their density) in the storage trie. +/// Some reserve is reserved to account future chain growth. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. +pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; + /// Maximum weight of single Millau block. /// /// This represents 0.5 seconds of compute assuming a target block time of six seconds. @@ -61,6 +69,20 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal weight of single message delivery transaction on Millau chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation +/// for the case when single message is delivered. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; + +/// Maximal weight of single message delivery confirmation transaction on Millau chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_delivery_proof` weight formula computation +/// for the case when single message is confirmed. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; + /// Block number type used in Millau. pub type BlockNumber = u64; @@ -280,3 +302,19 @@ sp_api::decl_runtime_apis! { fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::codec::Encode; + + #[test] + fn maximal_account_size_does_not_overflow_constant() { + assert!( + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + "Actual maximal size of encoded AccountId ({}) overflows expected ({})", + AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + ); + } +} diff --git a/bridges/primitives/rialto/src/lib.rs b/bridges/primitives/rialto/src/lib.rs index a514254b22565..b347ce5ec5f88 100644 --- a/bridges/primitives/rialto/src/lib.rs +++ b/bridges/primitives/rialto/src/lib.rs @@ -34,6 +34,14 @@ use sp_runtime::{ }; use sp_std::prelude::*; +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie. +/// Some reserve is reserved to account future chain growth. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. +pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; + /// Maximal weight of single Rialto block. /// /// This represents two seconds of compute assuming a target block time of six seconds. @@ -52,6 +60,20 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal weight of single message delivery transaction on Rialto chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation +/// for the case when single message is delivered. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; + +/// Maximal weight of single message delivery confirmation transaction on Rialto chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_delivery_proof` weight formula computation +/// for the case when single message is confirmed. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; + /// Block number type used in Rialto. pub type BlockNumber = u32; @@ -241,3 +263,19 @@ sp_api::decl_runtime_apis! { fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::codec::Encode; + + #[test] + fn maximal_account_size_does_not_overflow_constant() { + assert!( + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + "Actual maximal size of encoded AccountId ({}) overflows expected ({})", + AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + ); + } +}