diff --git a/bridges/bin/runtime-common/src/extensions/mod.rs b/bridges/bin/runtime-common/src/extensions/mod.rs
index 74bba5445bcff..690cfe1c8c680 100644
--- a/bridges/bin/runtime-common/src/extensions/mod.rs
+++ b/bridges/bin/runtime-common/src/extensions/mod.rs
@@ -17,5 +17,3 @@
//! Bridge-specific transaction extensions.
pub mod check_obsolete_extension;
-// TODO:(bridges-v2) - most of that stuff was introduced with free header execution: https://github.com/paritytech/polkadot-sdk/pull/4102, migrate to the `modules/relayers/src/extension`
-// pub mod priority_calculator;
diff --git a/bridges/bin/runtime-common/src/extensions/priority_calculator.rs b/bridges/bin/runtime-common/src/extensions/priority_calculator.rs
deleted file mode 100644
index 9f559dc13b64d..0000000000000
--- a/bridges/bin/runtime-common/src/extensions/priority_calculator.rs
+++ /dev/null
@@ -1,408 +0,0 @@
-// Copyright (C) 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 .
-
-//! Bridge transaction priority calculator.
-//!
-//! We want to prioritize message delivery transactions with more messages over
-//! transactions with less messages. That's because we reject delivery transactions
-//! if it contains already delivered message. And if some transaction delivers
-//! single message with nonce `N`, then the transaction with nonces `N..=N+100` will
-//! be rejected. This can lower bridge throughput down to one message per block.
-
-use frame_support::traits::Get;
-use sp_runtime::transaction_validity::TransactionPriority;
-
-// reexport everything from `integrity_tests` module
-#[allow(unused_imports)]
-pub use integrity_tests::*;
-
-/// We'll deal with different bridge items here - messages, headers, ...
-/// To avoid being too verbose with generic code, let's just define a separate alias.
-pub type ItemCount = u64;
-
-/// Compute priority boost for transaction that brings given number of bridge
-/// items (messages, headers, ...), when every additional item adds `PriorityBoostPerItem`
-/// to transaction priority.
-pub fn compute_priority_boost(n_items: ItemCount) -> TransactionPriority
-where
- PriorityBoostPerItem: Get,
-{
- // we don't want any boost for transaction with single (additional) item => minus one
- PriorityBoostPerItem::get().saturating_mul(n_items.saturating_sub(1))
-}
-
-#[cfg(not(feature = "integrity-test"))]
-mod integrity_tests {}
-
-#[cfg(feature = "integrity-test")]
-mod integrity_tests {
- use super::{compute_priority_boost, ItemCount};
- use crate::extensions::refund_relayer_extension::RefundableParachainId;
-
- use bp_messages::MessageNonce;
- use bp_runtime::PreComputedSize;
- use frame_support::{
- dispatch::{DispatchClass, DispatchInfo, Pays, PostDispatchInfo},
- traits::Get,
- };
- use pallet_transaction_payment::OnChargeTransaction;
- use sp_runtime::{
- traits::{Dispatchable, UniqueSaturatedInto, Zero},
- transaction_validity::TransactionPriority,
- FixedPointOperand, SaturatedConversion, Saturating,
- };
-
- type BalanceOf =
- <::OnChargeTransaction as OnChargeTransaction<
- T,
- >>::Balance;
-
- /// Ensures that the value of `PriorityBoostPerItem` matches the value of
- /// `tip_boost_per_item`.
- ///
- /// We want two transactions, `TX1` with `N` items and `TX2` with `N+1` items, have almost
- /// the same priority if we'll add `tip_boost_per_item` tip to the `TX1`. We want to be sure
- /// that if we add plain `PriorityBoostPerItem` priority to `TX1`, the priority will be close
- /// to `TX2` as well.
- fn ensure_priority_boost_is_sane(
- param_name: &str,
- max_items: ItemCount,
- tip_boost_per_item: Balance,
- estimate_priority: impl Fn(ItemCount, Balance) -> TransactionPriority,
- ) where
- PriorityBoostPerItem: Get,
- ItemCount: UniqueSaturatedInto,
- Balance: FixedPointOperand + Zero,
- {
- let priority_boost_per_item = PriorityBoostPerItem::get();
- for n_items in 1..=max_items {
- let base_priority = estimate_priority(n_items, Zero::zero());
- let priority_boost = compute_priority_boost::(n_items);
- let priority_with_boost = base_priority
- .checked_add(priority_boost)
- .expect("priority overflow: try lowering `max_items` or `tip_boost_per_item`?");
-
- let tip = tip_boost_per_item.saturating_mul((n_items - 1).unique_saturated_into());
- let priority_with_tip = estimate_priority(1, tip);
-
- const ERROR_MARGIN: TransactionPriority = 5; // 5%
- if priority_with_boost.abs_diff(priority_with_tip).saturating_mul(100) /
- priority_with_tip >
- ERROR_MARGIN
- {
- panic!(
- "The {param_name} value ({}) must be fixed to: {}",
- priority_boost_per_item,
- compute_priority_boost_per_item(
- max_items,
- tip_boost_per_item,
- estimate_priority
- ),
- );
- }
- }
- }
-
- /// Compute priority boost that we give to bridge transaction for every
- /// additional bridge item.
- #[cfg(feature = "integrity-test")]
- fn compute_priority_boost_per_item(
- max_items: ItemCount,
- tip_boost_per_item: Balance,
- estimate_priority: impl Fn(ItemCount, Balance) -> TransactionPriority,
- ) -> TransactionPriority
- where
- ItemCount: UniqueSaturatedInto,
- Balance: FixedPointOperand + Zero,
- {
- // estimate priority of transaction that delivers one item and has large tip
- let small_with_tip_priority =
- estimate_priority(1, tip_boost_per_item.saturating_mul(max_items.saturated_into()));
- // estimate priority of transaction that delivers maximal number of items, but has no tip
- let large_without_tip_priority = estimate_priority(max_items, Zero::zero());
-
- small_with_tip_priority
- .saturating_sub(large_without_tip_priority)
- .saturating_div(max_items - 1)
- }
-
- /// Computations, specific to bridge relay chains transactions.
- pub mod per_relay_header {
- use super::*;
-
- use bp_header_chain::{
- max_expected_submit_finality_proof_arguments_size, ChainWithGrandpa,
- };
- use pallet_bridge_grandpa::WeightInfoExt;
-
- /// Ensures that the value of `PriorityBoostPerHeader` matches the value of
- /// `tip_boost_per_header`.
- ///
- /// We want two transactions, `TX1` with `N` headers and `TX2` with `N+1` headers, have
- /// almost the same priority if we'll add `tip_boost_per_header` tip to the `TX1`. We want
- /// to be sure that if we add plain `PriorityBoostPerHeader` priority to `TX1`, the priority
- /// will be close to `TX2` as well.
- pub fn ensure_priority_boost_is_sane(
- tip_boost_per_header: BalanceOf,
- ) where
- Runtime:
- pallet_transaction_payment::Config + pallet_bridge_grandpa::Config,
- GrandpaInstance: 'static,
- PriorityBoostPerHeader: Get,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- // the meaning of `max_items` here is different when comparing with message
- // transactions - with messages we have a strict limit on maximal number of
- // messages we can fit into a single transaction. With headers, current best
- // header may be improved by any "number of items". But this number is only
- // used to verify priority boost, so it should be fine to select this arbitrary
- // value - it SHALL NOT affect any value, it just adds more tests for the value.
- let maximal_improved_by = 4_096;
- super::ensure_priority_boost_is_sane::>(
- "PriorityBoostPerRelayHeader",
- maximal_improved_by,
- tip_boost_per_header,
- |_n_headers, tip| {
- estimate_relay_header_submit_transaction_priority::(
- tip,
- )
- },
- );
- }
-
- /// Estimate relay header delivery transaction priority.
- #[cfg(feature = "integrity-test")]
- fn estimate_relay_header_submit_transaction_priority(
- tip: BalanceOf,
- ) -> TransactionPriority
- where
- Runtime:
- pallet_transaction_payment::Config + pallet_bridge_grandpa::Config,
- GrandpaInstance: 'static,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- // just an estimation of extra transaction bytes that are added to every transaction
- // (including signature, signed extensions extra and etc + in our case it includes
- // all call arguments except the proof itself)
- let base_tx_size = 512;
- // let's say we are relaying largest relay chain headers
- let tx_call_size = max_expected_submit_finality_proof_arguments_size::<
- Runtime::BridgedChain,
- >(true, Runtime::BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1);
-
- // finally we are able to estimate transaction size and weight
- let transaction_size = base_tx_size.saturating_add(tx_call_size);
- let transaction_weight = Runtime::WeightInfo::submit_finality_proof_weight(
- Runtime::BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1,
- Runtime::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY,
- );
-
- pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
- &DispatchInfo {
- weight: transaction_weight,
- class: DispatchClass::Normal,
- pays_fee: Pays::Yes,
- },
- transaction_size as _,
- tip,
- Zero::zero(),
- )
- }
- }
-
- /// Computations, specific to bridge parachains transactions.
- pub mod per_parachain_header {
- use super::*;
-
- use bp_runtime::Parachain;
- use pallet_bridge_parachains::WeightInfoExt;
-
- /// Ensures that the value of `PriorityBoostPerHeader` matches the value of
- /// `tip_boost_per_header`.
- ///
- /// We want two transactions, `TX1` with `N` headers and `TX2` with `N+1` headers, have
- /// almost the same priority if we'll add `tip_boost_per_header` tip to the `TX1`. We want
- /// to be sure that if we add plain `PriorityBoostPerHeader` priority to `TX1`, the priority
- /// will be close to `TX2` as well.
- pub fn ensure_priority_boost_is_sane(
- tip_boost_per_header: BalanceOf,
- ) where
- Runtime: pallet_transaction_payment::Config
- + pallet_bridge_parachains::Config,
- RefundableParachain: RefundableParachainId,
- PriorityBoostPerHeader: Get,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- // the meaning of `max_items` here is different when comparing with message
- // transactions - with messages we have a strict limit on maximal number of
- // messages we can fit into a single transaction. With headers, current best
- // header may be improved by any "number of items". But this number is only
- // used to verify priority boost, so it should be fine to select this arbitrary
- // value - it SHALL NOT affect any value, it just adds more tests for the value.
- let maximal_improved_by = 4_096;
- super::ensure_priority_boost_is_sane::>(
- "PriorityBoostPerParachainHeader",
- maximal_improved_by,
- tip_boost_per_header,
- |_n_headers, tip| {
- estimate_parachain_header_submit_transaction_priority::<
- Runtime,
- RefundableParachain,
- >(tip)
- },
- );
- }
-
- /// Estimate parachain header delivery transaction priority.
- #[cfg(feature = "integrity-test")]
- fn estimate_parachain_header_submit_transaction_priority(
- tip: BalanceOf,
- ) -> TransactionPriority
- where
- Runtime: pallet_transaction_payment::Config
- + pallet_bridge_parachains::Config,
- RefundableParachain: RefundableParachainId,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- // just an estimation of extra transaction bytes that are added to every transaction
- // (including signature, signed extensions extra and etc + in our case it includes
- // all call arguments except the proof itself)
- let base_tx_size = 512;
- // let's say we are relaying largest parachain headers and proof takes some more bytes
- let tx_call_size = >::WeightInfo::expected_extra_storage_proof_size()
- .saturating_add(RefundableParachain::BridgedChain::MAX_HEADER_SIZE);
-
- // finally we are able to estimate transaction size and weight
- let transaction_size = base_tx_size.saturating_add(tx_call_size);
- let transaction_weight = >::WeightInfo::submit_parachain_heads_weight(
- Runtime::DbWeight::get(),
- &PreComputedSize(transaction_size as _),
- // just one parachain - all other submissions won't receive any boost
- 1,
- );
-
- pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
- &DispatchInfo {
- weight: transaction_weight,
- class: DispatchClass::Normal,
- pays_fee: Pays::Yes,
- },
- transaction_size as _,
- tip,
- Zero::zero(),
- )
- }
- }
-
- /// Computations, specific to bridge messages transactions.
- pub mod per_message {
- use super::*;
-
- use bp_messages::ChainWithMessages;
- use pallet_bridge_messages::WeightInfoExt;
-
- /// Ensures that the value of `PriorityBoostPerMessage` matches the value of
- /// `tip_boost_per_message`.
- ///
- /// We want two transactions, `TX1` with `N` messages and `TX2` with `N+1` messages, have
- /// almost the same priority if we'll add `tip_boost_per_message` tip to the `TX1`. We want
- /// to be sure that if we add plain `PriorityBoostPerMessage` priority to `TX1`, the
- /// priority will be close to `TX2` as well.
- pub fn ensure_priority_boost_is_sane(
- tip_boost_per_message: BalanceOf,
- ) where
- Runtime: pallet_transaction_payment::Config
- + pallet_bridge_messages::Config,
- MessagesInstance: 'static,
- PriorityBoostPerMessage: Get,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- let maximal_messages_in_delivery_transaction =
- Runtime::BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
- super::ensure_priority_boost_is_sane::>(
- "PriorityBoostPerMessage",
- maximal_messages_in_delivery_transaction,
- tip_boost_per_message,
- |n_messages, tip| {
- estimate_message_delivery_transaction_priority::(
- n_messages, tip,
- )
- },
- );
- }
-
- /// Estimate message delivery transaction priority.
- #[cfg(feature = "integrity-test")]
- fn estimate_message_delivery_transaction_priority(
- messages: MessageNonce,
- tip: BalanceOf,
- ) -> TransactionPriority
- where
- Runtime: pallet_transaction_payment::Config
- + pallet_bridge_messages::Config,
- MessagesInstance: 'static,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- // just an estimation of extra transaction bytes that are added to every transaction
- // (including signature, signed extensions extra and etc + in our case it includes
- // all call arguments except the proof itself)
- let base_tx_size = 512;
- // let's say we are relaying similar small messages and for every message we add more
- // trie nodes to the proof (x0.5 because we expect some nodes to be reused)
- let estimated_message_size = 512;
- // let's say all our messages have the same dispatch weight
- let estimated_message_dispatch_weight =
- Runtime::WeightInfo::message_dispatch_weight(estimated_message_size);
- // messages proof argument size is (for every message) messages size + some additional
- // trie nodes. Some of them are reused by different messages, so let's take 2/3 of
- // default "overhead" constant
- let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size()
- .saturating_mul(2)
- .saturating_div(3)
- .saturating_add(estimated_message_size)
- .saturating_mul(messages as _);
-
- // finally we are able to estimate transaction size and weight
- let transaction_size = base_tx_size.saturating_add(messages_proof_size);
- let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight(
- &PreComputedSize(transaction_size as _),
- messages as _,
- estimated_message_dispatch_weight.saturating_mul(messages),
- );
-
- pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
- &DispatchInfo {
- weight: transaction_weight,
- class: DispatchClass::Normal,
- pays_fee: Pays::Yes,
- },
- transaction_size as _,
- tip,
- Zero::zero(),
- )
- }
- }
-}
diff --git a/bridges/modules/relayers/src/extension/priority.rs b/bridges/modules/relayers/src/extension/priority.rs
index 14511ad2545f1..f96d8632592f5 100644
--- a/bridges/modules/relayers/src/extension/priority.rs
+++ b/bridges/modules/relayers/src/extension/priority.rs
@@ -22,23 +22,25 @@
//! single message with nonce `N`, then the transaction with nonces `N..=N+100` will
//! be rejected. This can lower bridge throughput down to one message per block.
-use bp_messages::MessageNonce;
use frame_support::traits::Get;
use sp_runtime::transaction_validity::TransactionPriority;
// reexport everything from `integrity_tests` module
pub use integrity_tests::*;
-/// Compute priority boost for message delivery transaction that delivers
-/// given number of messages.
-pub fn compute_priority_boost(
- messages: MessageNonce,
-) -> TransactionPriority
+/// We'll deal with different bridge items here - messages, headers, ...
+/// To avoid being too verbose with generic code, let's just define a separate alias.
+pub type ItemCount = u64;
+
+/// Compute priority boost for transaction that brings given number of bridge
+/// items (messages, headers, ...), when every additional item adds `PriorityBoostPerItem`
+/// to transaction priority.
+pub fn compute_priority_boost(n_items: ItemCount) -> TransactionPriority
where
- PriorityBoostPerMessage: Get,
+ PriorityBoostPerItem: Get,
{
- // we don't want any boost for transaction with single message => minus one
- PriorityBoostPerMessage::get().saturating_mul(messages.saturating_sub(1))
+ // we don't want any boost for transaction with single (additional) item => minus one
+ PriorityBoostPerItem::get().saturating_mul(n_items.saturating_sub(1))
}
#[cfg(not(feature = "integrity-test"))]
@@ -46,8 +48,7 @@ mod integrity_tests {}
#[cfg(feature = "integrity-test")]
mod integrity_tests {
- use super::compute_priority_boost;
- use bp_messages::ChainWithMessages;
+ use super::{compute_priority_boost, ItemCount};
use bp_messages::MessageNonce;
use bp_runtime::PreComputedSize;
@@ -55,7 +56,6 @@ mod integrity_tests {
dispatch::{DispatchClass, DispatchInfo, Pays, PostDispatchInfo},
traits::Get,
};
- use pallet_bridge_messages::WeightInfoExt;
use pallet_transaction_payment::OnChargeTransaction;
use sp_runtime::{
traits::{Dispatchable, UniqueSaturatedInto, Zero},
@@ -68,37 +68,33 @@ mod integrity_tests {
T,
>>::Balance;
- /// Ensures that the value of `PriorityBoostPerMessage` matches the value of
- /// `tip_boost_per_message`.
+ /// Ensures that the value of `PriorityBoostPerItem` matches the value of
+ /// `tip_boost_per_item`.
///
- /// We want two transactions, `TX1` with `N` messages and `TX2` with `N+1` messages, have almost
- /// the same priority if we'll add `tip_boost_per_message` tip to the `TX1`. We want to be sure
- /// that if we add plain `PriorityBoostPerMessage` priority to `TX1`, the priority will be close
+ /// We want two transactions, `TX1` with `N` items and `TX2` with `N+1` items, have almost
+ /// the same priority if we'll add `tip_boost_per_item` tip to the `TX1`. We want to be sure
+ /// that if we add plain `PriorityBoostPerItem` priority to `TX1`, the priority will be close
/// to `TX2` as well.
- pub fn ensure_priority_boost_is_sane(
- tip_boost_per_message: BalanceOf,
+ fn ensure_priority_boost_is_sane(
+ param_name: &str,
+ max_items: ItemCount,
+ tip_boost_per_item: Balance,
+ estimate_priority: impl Fn(ItemCount, Balance) -> TransactionPriority,
) where
- Runtime:
- pallet_transaction_payment::Config + pallet_bridge_messages::Config,
- MessagesInstance: 'static,
- PriorityBoostPerMessage: Get,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
+ PriorityBoostPerItem: Get,
+ ItemCount: UniqueSaturatedInto,
+ Balance: FixedPointOperand + Zero,
{
- let priority_boost_per_message = PriorityBoostPerMessage::get();
- let maximal_messages_in_delivery_transaction =
- Runtime::BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
- for messages in 1..=maximal_messages_in_delivery_transaction {
- let base_priority = estimate_message_delivery_transaction_priority::<
- Runtime,
- MessagesInstance,
- >(messages, Zero::zero());
- let priority_boost = compute_priority_boost::(messages);
- let priority_with_boost = base_priority + priority_boost;
-
- let tip = tip_boost_per_message.saturating_mul((messages - 1).unique_saturated_into());
- let priority_with_tip =
- estimate_message_delivery_transaction_priority::(1, tip);
+ let priority_boost_per_item = PriorityBoostPerItem::get();
+ for n_items in 1..=max_items {
+ let base_priority = estimate_priority(n_items, Zero::zero());
+ let priority_boost = compute_priority_boost::(n_items);
+ let priority_with_boost = base_priority
+ .checked_add(priority_boost)
+ .expect("priority overflow: try lowering `max_items` or `tip_boost_per_item`?");
+
+ let tip = tip_boost_per_item.saturating_mul((n_items - 1).unique_saturated_into());
+ let priority_with_tip = estimate_priority(1, tip);
const ERROR_MARGIN: TransactionPriority = 5; // 5%
if priority_with_boost.abs_diff(priority_with_tip).saturating_mul(100) /
@@ -106,97 +102,308 @@ mod integrity_tests {
ERROR_MARGIN
{
panic!(
- "The PriorityBoostPerMessage value ({}) must be fixed to: {}",
- priority_boost_per_message,
- compute_priority_boost_per_message::(
- tip_boost_per_message
+ "The {param_name} value ({}) must be fixed to: {}",
+ priority_boost_per_item,
+ compute_priority_boost_per_item(
+ max_items,
+ tip_boost_per_item,
+ estimate_priority
),
);
}
}
}
- /// Compute priority boost that we give to message delivery transaction for additional message.
+ /// Compute priority boost that we give to bridge transaction for every
+ /// additional bridge item.
#[cfg(feature = "integrity-test")]
- fn compute_priority_boost_per_message(
- tip_boost_per_message: BalanceOf,
+ fn compute_priority_boost_per_item(
+ max_items: ItemCount,
+ tip_boost_per_item: Balance,
+ estimate_priority: impl Fn(ItemCount, Balance) -> TransactionPriority,
) -> TransactionPriority
where
- Runtime:
- pallet_transaction_payment::Config + pallet_bridge_messages::Config,
- MessagesInstance: 'static,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
+ ItemCount: UniqueSaturatedInto,
+ Balance: FixedPointOperand + Zero,
{
- // esimate priority of transaction that delivers one message and has large tip
- let maximal_messages_in_delivery_transaction =
- Runtime::BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
+ // estimate priority of transaction that delivers one item and has large tip
let small_with_tip_priority =
- estimate_message_delivery_transaction_priority::(
- 1,
- tip_boost_per_message
- .saturating_mul(maximal_messages_in_delivery_transaction.saturated_into()),
- );
- // estimate priority of transaction that delivers maximal number of messages, but has no tip
- let large_without_tip_priority = estimate_message_delivery_transaction_priority::<
- Runtime,
- MessagesInstance,
- >(maximal_messages_in_delivery_transaction, Zero::zero());
+ estimate_priority(1, tip_boost_per_item.saturating_mul(max_items.saturated_into()));
+ // estimate priority of transaction that delivers maximal number of items, but has no tip
+ let large_without_tip_priority = estimate_priority(max_items, Zero::zero());
small_with_tip_priority
.saturating_sub(large_without_tip_priority)
- .saturating_div(maximal_messages_in_delivery_transaction - 1)
+ .saturating_div(max_items - 1)
}
- /// Estimate message delivery transaction priority.
- #[cfg(feature = "integrity-test")]
- fn estimate_message_delivery_transaction_priority(
- messages: MessageNonce,
- tip: BalanceOf,
- ) -> TransactionPriority
- where
- Runtime:
- pallet_transaction_payment::Config + pallet_bridge_messages::Config,
- MessagesInstance: 'static,
- Runtime::RuntimeCall: Dispatchable,
- BalanceOf: Send + Sync + FixedPointOperand,
- {
- // just an estimation of extra transaction bytes that are added to every transaction
- // (including signature, signed extensions extra and etc + in our case it includes
- // all call arguments extept the proof itself)
- let base_tx_size = 512;
- // let's say we are relaying similar small messages and for every message we add more trie
- // nodes to the proof (x0.5 because we expect some nodes to be reused)
- let estimated_message_size = 512;
- // let's say all our messages have the same dispatch weight
- let estimated_message_dispatch_weight =
- Runtime::WeightInfo::message_dispatch_weight(estimated_message_size);
- // messages proof argument size is (for every message) messages size + some additional
- // trie nodes. Some of them are reused by different messages, so let's take 2/3 of default
- // "overhead" constant
- let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size()
- .saturating_mul(2)
- .saturating_div(3)
- .saturating_add(estimated_message_size)
- .saturating_mul(messages as _);
-
- // finally we are able to estimate transaction size and weight
- let transaction_size = base_tx_size.saturating_add(messages_proof_size);
- let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight(
- &PreComputedSize(transaction_size as _),
- messages as _,
- estimated_message_dispatch_weight.saturating_mul(messages),
- );
-
- pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
- &DispatchInfo {
- weight: transaction_weight,
- class: DispatchClass::Normal,
- pays_fee: Pays::Yes,
- },
- transaction_size as _,
- tip,
- Zero::zero(),
- )
+ /// Computations, specific to bridge relay chains transactions.
+ pub mod per_relay_header {
+ use super::*;
+
+ use bp_header_chain::{
+ max_expected_submit_finality_proof_arguments_size, ChainWithGrandpa,
+ };
+ use pallet_bridge_grandpa::WeightInfoExt;
+
+ /// Ensures that the value of `PriorityBoostPerHeader` matches the value of
+ /// `tip_boost_per_header`.
+ ///
+ /// We want two transactions, `TX1` with `N` headers and `TX2` with `N+1` headers, have
+ /// almost the same priority if we'll add `tip_boost_per_header` tip to the `TX1`. We want
+ /// to be sure that if we add plain `PriorityBoostPerHeader` priority to `TX1`, the priority
+ /// will be close to `TX2` as well.
+ pub fn ensure_priority_boost_is_sane(
+ tip_boost_per_header: BalanceOf,
+ ) where
+ Runtime:
+ pallet_transaction_payment::Config + pallet_bridge_grandpa::Config,
+ GrandpaInstance: 'static,
+ PriorityBoostPerHeader: Get,
+ Runtime::RuntimeCall: Dispatchable,
+ BalanceOf: Send + Sync + FixedPointOperand,
+ {
+ // the meaning of `max_items` here is different when comparing with message
+ // transactions - with messages we have a strict limit on maximal number of
+ // messages we can fit into a single transaction. With headers, current best
+ // header may be improved by any "number of items". But this number is only
+ // used to verify priority boost, so it should be fine to select this arbitrary
+ // value - it SHALL NOT affect any value, it just adds more tests for the value.
+ let maximal_improved_by = 4_096;
+ super::ensure_priority_boost_is_sane::>(
+ "PriorityBoostPerRelayHeader",
+ maximal_improved_by,
+ tip_boost_per_header,
+ |_n_headers, tip| {
+ estimate_relay_header_submit_transaction_priority::(
+ tip,
+ )
+ },
+ );
+ }
+
+ /// Estimate relay header delivery transaction priority.
+ #[cfg(feature = "integrity-test")]
+ fn estimate_relay_header_submit_transaction_priority(
+ tip: BalanceOf,
+ ) -> TransactionPriority
+ where
+ Runtime:
+ pallet_transaction_payment::Config + pallet_bridge_grandpa::Config,
+ GrandpaInstance: 'static,
+ Runtime::RuntimeCall: Dispatchable,
+ BalanceOf: Send + Sync + FixedPointOperand,
+ {
+ // just an estimation of extra transaction bytes that are added to every transaction
+ // (including signature, signed extensions extra and etc + in our case it includes
+ // all call arguments except the proof itself)
+ let base_tx_size = 512;
+ // let's say we are relaying largest relay chain headers
+ let tx_call_size = max_expected_submit_finality_proof_arguments_size::<
+ Runtime::BridgedChain,
+ >(true, Runtime::BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1);
+
+ // finally we are able to estimate transaction size and weight
+ let transaction_size = base_tx_size.saturating_add(tx_call_size);
+ let transaction_weight = Runtime::WeightInfo::submit_finality_proof_weight(
+ Runtime::BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1,
+ Runtime::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY,
+ );
+
+ pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
+ &DispatchInfo {
+ weight: transaction_weight,
+ class: DispatchClass::Normal,
+ pays_fee: Pays::Yes,
+ },
+ transaction_size as _,
+ tip,
+ Zero::zero(),
+ )
+ }
+ }
+
+ /// Computations, specific to bridge parachains transactions.
+ pub mod per_parachain_header {
+ use super::*;
+
+ use bp_runtime::Parachain;
+ use pallet_bridge_parachains::WeightInfoExt;
+
+ /// Ensures that the value of `PriorityBoostPerHeader` matches the value of
+ /// `tip_boost_per_header`.
+ ///
+ /// We want two transactions, `TX1` with `N` headers and `TX2` with `N+1` headers, have
+ /// almost the same priority if we'll add `tip_boost_per_header` tip to the `TX1`. We want
+ /// to be sure that if we add plain `PriorityBoostPerHeader` priority to `TX1`, the priority
+ /// will be close to `TX2` as well.
+ pub fn ensure_priority_boost_is_sane(
+ tip_boost_per_header: BalanceOf,
+ ) where
+ Runtime: pallet_transaction_payment::Config
+ + pallet_bridge_parachains::Config,
+ ParachainsInstance: 'static,
+ Para: Parachain,
+ PriorityBoostPerHeader: Get,
+ Runtime::RuntimeCall: Dispatchable,
+ BalanceOf: Send + Sync + FixedPointOperand,
+ {
+ // the meaning of `max_items` here is different when comparing with message
+ // transactions - with messages we have a strict limit on maximal number of
+ // messages we can fit into a single transaction. With headers, current best
+ // header may be improved by any "number of items". But this number is only
+ // used to verify priority boost, so it should be fine to select this arbitrary
+ // value - it SHALL NOT affect any value, it just adds more tests for the value.
+ let maximal_improved_by = 4_096;
+ super::ensure_priority_boost_is_sane::>(
+ "PriorityBoostPerParachainHeader",
+ maximal_improved_by,
+ tip_boost_per_header,
+ |_n_headers, tip| {
+ estimate_parachain_header_submit_transaction_priority::<
+ Runtime,
+ ParachainsInstance,
+ Para,
+ >(tip)
+ },
+ );
+ }
+
+ /// Estimate parachain header delivery transaction priority.
+ #[cfg(feature = "integrity-test")]
+ fn estimate_parachain_header_submit_transaction_priority(
+ tip: BalanceOf,
+ ) -> TransactionPriority
+ where
+ Runtime: pallet_transaction_payment::Config
+ + pallet_bridge_parachains::Config,
+ ParachainsInstance: 'static,
+ Para: Parachain,
+ Runtime::RuntimeCall: Dispatchable,
+ BalanceOf: Send + Sync + FixedPointOperand,
+ {
+ // just an estimation of extra transaction bytes that are added to every transaction
+ // (including signature, signed extensions extra and etc + in our case it includes
+ // all call arguments except the proof itself)
+ let base_tx_size = 512;
+ // let's say we are relaying largest parachain headers and proof takes some more bytes
+ let tx_call_size = >::WeightInfo::expected_extra_storage_proof_size()
+ .saturating_add(Para::MAX_HEADER_SIZE);
+
+ // finally we are able to estimate transaction size and weight
+ let transaction_size = base_tx_size.saturating_add(tx_call_size);
+ let transaction_weight = >::WeightInfo::submit_parachain_heads_weight(
+ Runtime::DbWeight::get(),
+ &PreComputedSize(transaction_size as _),
+ // just one parachain - all other submissions won't receive any boost
+ 1,
+ );
+
+ pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
+ &DispatchInfo {
+ weight: transaction_weight,
+ class: DispatchClass::Normal,
+ pays_fee: Pays::Yes,
+ },
+ transaction_size as _,
+ tip,
+ Zero::zero(),
+ )
+ }
+ }
+
+ /// Computations, specific to bridge messages transactions.
+ pub mod per_message {
+ use super::*;
+
+ use bp_messages::ChainWithMessages;
+ use pallet_bridge_messages::WeightInfoExt;
+
+ /// Ensures that the value of `PriorityBoostPerMessage` matches the value of
+ /// `tip_boost_per_message`.
+ ///
+ /// We want two transactions, `TX1` with `N` messages and `TX2` with `N+1` messages, have
+ /// almost the same priority if we'll add `tip_boost_per_message` tip to the `TX1`. We want
+ /// to be sure that if we add plain `PriorityBoostPerMessage` priority to `TX1`, the
+ /// priority will be close to `TX2` as well.
+ pub fn ensure_priority_boost_is_sane(
+ tip_boost_per_message: BalanceOf,
+ ) where
+ Runtime: pallet_transaction_payment::Config
+ + pallet_bridge_messages::Config,
+ MessagesInstance: 'static,
+ PriorityBoostPerMessage: Get,
+ Runtime::RuntimeCall: Dispatchable,
+ BalanceOf: Send + Sync + FixedPointOperand,
+ {
+ let maximal_messages_in_delivery_transaction =
+ Runtime::BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
+ super::ensure_priority_boost_is_sane::>(
+ "PriorityBoostPerMessage",
+ maximal_messages_in_delivery_transaction,
+ tip_boost_per_message,
+ |n_messages, tip| {
+ estimate_message_delivery_transaction_priority::(
+ n_messages, tip,
+ )
+ },
+ );
+ }
+
+ /// Estimate message delivery transaction priority.
+ #[cfg(feature = "integrity-test")]
+ fn estimate_message_delivery_transaction_priority(
+ messages: MessageNonce,
+ tip: BalanceOf,
+ ) -> TransactionPriority
+ where
+ Runtime: pallet_transaction_payment::Config
+ + pallet_bridge_messages::Config,
+ MessagesInstance: 'static,
+ Runtime::RuntimeCall: Dispatchable,
+ BalanceOf: Send + Sync + FixedPointOperand,
+ {
+ // just an estimation of extra transaction bytes that are added to every transaction
+ // (including signature, signed extensions extra and etc + in our case it includes
+ // all call arguments except the proof itself)
+ let base_tx_size = 512;
+ // let's say we are relaying similar small messages and for every message we add more
+ // trie nodes to the proof (x0.5 because we expect some nodes to be reused)
+ let estimated_message_size = 512;
+ // let's say all our messages have the same dispatch weight
+ let estimated_message_dispatch_weight =
+ Runtime::WeightInfo::message_dispatch_weight(estimated_message_size);
+ // messages proof argument size is (for every message) messages size + some additional
+ // trie nodes. Some of them are reused by different messages, so let's take 2/3 of
+ // default "overhead" constant
+ let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size()
+ .saturating_mul(2)
+ .saturating_div(3)
+ .saturating_add(estimated_message_size)
+ .saturating_mul(messages as _);
+
+ // finally we are able to estimate transaction size and weight
+ let transaction_size = base_tx_size.saturating_add(messages_proof_size);
+ let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight(
+ &PreComputedSize(transaction_size as _),
+ messages as _,
+ estimated_message_dispatch_weight.saturating_mul(messages),
+ );
+
+ pallet_transaction_payment::ChargeTransactionPayment::::get_priority(
+ &DispatchInfo {
+ weight: transaction_weight,
+ class: DispatchClass::Normal,
+ pays_fee: Pays::Yes,
+ },
+ transaction_size as _,
+ tip,
+ Zero::zero(),
+ )
+ }
}
}