1use frame_support::traits::Get;
26use sp_runtime::transaction_validity::TransactionPriority;
27
28#[allow(unused_imports)]
30pub use integrity_tests::*;
31
32pub type ItemCount = u64;
35
36pub fn compute_priority_boost<PriorityBoostPerItem>(n_items: ItemCount) -> TransactionPriority
40where
41 PriorityBoostPerItem: Get<TransactionPriority>,
42{
43 PriorityBoostPerItem::get().saturating_mul(n_items.saturating_sub(1))
45}
46
47#[cfg(not(feature = "integrity-test"))]
48mod integrity_tests {}
49
50#[cfg(feature = "integrity-test")]
51mod integrity_tests {
52 use super::{compute_priority_boost, ItemCount};
53
54 use bp_messages::MessageNonce;
55 use bp_runtime::PreComputedSize;
56 use frame_support::{
57 dispatch::{DispatchClass, DispatchInfo, Pays, PostDispatchInfo},
58 traits::Get,
59 };
60 use pallet_transaction_payment::OnChargeTransaction;
61 use sp_runtime::{
62 traits::{Dispatchable, UniqueSaturatedInto, Zero},
63 transaction_validity::TransactionPriority,
64 FixedPointOperand, SaturatedConversion, Saturating,
65 };
66
67 type BalanceOf<T> =
68 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as OnChargeTransaction<
69 T,
70 >>::Balance;
71
72 fn ensure_priority_boost_is_sane<PriorityBoostPerItem, Balance>(
80 param_name: &str,
81 max_items: ItemCount,
82 tip_boost_per_item: Balance,
83 estimate_priority: impl Fn(ItemCount, Balance) -> TransactionPriority,
84 ) where
85 PriorityBoostPerItem: Get<TransactionPriority>,
86 ItemCount: UniqueSaturatedInto<Balance>,
87 Balance: FixedPointOperand + Zero,
88 {
89 let priority_boost_per_item = PriorityBoostPerItem::get();
90 for n_items in 1..=max_items {
91 let base_priority = estimate_priority(n_items, Zero::zero());
92 let priority_boost = compute_priority_boost::<PriorityBoostPerItem>(n_items);
93 let priority_with_boost = base_priority
94 .checked_add(priority_boost)
95 .expect("priority overflow: try lowering `max_items` or `tip_boost_per_item`?");
96
97 let tip = tip_boost_per_item.saturating_mul((n_items - 1).unique_saturated_into());
98 let priority_with_tip = estimate_priority(1, tip);
99
100 const ERROR_MARGIN: TransactionPriority = 5; if priority_with_boost.abs_diff(priority_with_tip).saturating_mul(100) /
102 priority_with_tip >
103 ERROR_MARGIN
104 {
105 panic!(
106 "The {param_name} value ({}) must be fixed to: {}",
107 priority_boost_per_item,
108 compute_priority_boost_per_item(
109 max_items,
110 tip_boost_per_item,
111 estimate_priority
112 ),
113 );
114 }
115 }
116 }
117
118 #[cfg(feature = "integrity-test")]
121 fn compute_priority_boost_per_item<Balance>(
122 max_items: ItemCount,
123 tip_boost_per_item: Balance,
124 estimate_priority: impl Fn(ItemCount, Balance) -> TransactionPriority,
125 ) -> TransactionPriority
126 where
127 ItemCount: UniqueSaturatedInto<Balance>,
128 Balance: FixedPointOperand + Zero,
129 {
130 let small_with_tip_priority =
132 estimate_priority(1, tip_boost_per_item.saturating_mul(max_items.saturated_into()));
133 let large_without_tip_priority = estimate_priority(max_items, Zero::zero());
135
136 small_with_tip_priority
137 .saturating_sub(large_without_tip_priority)
138 .saturating_div(max_items - 1)
139 }
140
141 pub mod per_relay_header {
143 use super::*;
144
145 use bp_header_chain::{
146 max_expected_submit_finality_proof_arguments_size, ChainWithGrandpa,
147 };
148 use pallet_bridge_grandpa::WeightInfoExt;
149
150 pub fn ensure_priority_boost_is_sane<Runtime, GrandpaInstance, PriorityBoostPerHeader>(
158 tip_boost_per_header: BalanceOf<Runtime>,
159 ) where
160 Runtime:
161 pallet_transaction_payment::Config + pallet_bridge_grandpa::Config<GrandpaInstance>,
162 GrandpaInstance: 'static,
163 PriorityBoostPerHeader: Get<TransactionPriority>,
164 Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
165 BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
166 {
167 let maximal_improved_by = 4_096;
174 super::ensure_priority_boost_is_sane::<PriorityBoostPerHeader, BalanceOf<Runtime>>(
175 "PriorityBoostPerRelayHeader",
176 maximal_improved_by,
177 tip_boost_per_header,
178 |_n_headers, tip| {
179 estimate_relay_header_submit_transaction_priority::<Runtime, GrandpaInstance>(
180 tip,
181 )
182 },
183 );
184 }
185
186 #[cfg(feature = "integrity-test")]
188 fn estimate_relay_header_submit_transaction_priority<Runtime, GrandpaInstance>(
189 tip: BalanceOf<Runtime>,
190 ) -> TransactionPriority
191 where
192 Runtime:
193 pallet_transaction_payment::Config + pallet_bridge_grandpa::Config<GrandpaInstance>,
194 GrandpaInstance: 'static,
195 Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
196 BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
197 {
198 let base_tx_size = 512;
202 let tx_call_size = max_expected_submit_finality_proof_arguments_size::<
204 Runtime::BridgedChain,
205 >(true, Runtime::BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1);
206
207 let transaction_size = base_tx_size.saturating_add(tx_call_size);
209 let transaction_weight = <Runtime as ::pallet_bridge_grandpa::Config<
210 GrandpaInstance,
211 >>::WeightInfo::submit_finality_proof_weight(
212 Runtime::BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1,
213 Runtime::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY,
214 );
215
216 pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::get_priority(
217 &DispatchInfo {
218 call_weight: transaction_weight,
219 extension_weight: Default::default(),
220 class: DispatchClass::Normal,
221 pays_fee: Pays::Yes,
222 },
223 transaction_size as _,
224 tip,
225 Zero::zero(),
226 )
227 }
228 }
229
230 pub mod per_parachain_header {
232 use super::*;
233
234 use bp_runtime::Parachain;
235 use pallet_bridge_parachains::WeightInfoExt;
236
237 pub fn ensure_priority_boost_is_sane<
245 Runtime,
246 ParachainsInstance,
247 Para,
248 PriorityBoostPerHeader,
249 >(
250 tip_boost_per_header: BalanceOf<Runtime>,
251 ) where
252 Runtime: pallet_transaction_payment::Config
253 + pallet_bridge_parachains::Config<ParachainsInstance>,
254 ParachainsInstance: 'static,
255 Para: Parachain,
256 PriorityBoostPerHeader: Get<TransactionPriority>,
257 Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
258 BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
259 {
260 let maximal_improved_by = 4_096;
267 super::ensure_priority_boost_is_sane::<PriorityBoostPerHeader, BalanceOf<Runtime>>(
268 "PriorityBoostPerParachainHeader",
269 maximal_improved_by,
270 tip_boost_per_header,
271 |_n_headers, tip| {
272 estimate_parachain_header_submit_transaction_priority::<
273 Runtime,
274 ParachainsInstance,
275 Para,
276 >(tip)
277 },
278 );
279 }
280
281 #[cfg(feature = "integrity-test")]
283 fn estimate_parachain_header_submit_transaction_priority<
284 Runtime,
285 ParachainsInstance,
286 Para,
287 >(
288 tip: BalanceOf<Runtime>,
289 ) -> TransactionPriority
290 where
291 Runtime: pallet_transaction_payment::Config
292 + pallet_bridge_parachains::Config<ParachainsInstance>,
293 ParachainsInstance: 'static,
294 Para: Parachain,
295 Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
296 BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
297 {
298 let base_tx_size = 512;
302 let tx_call_size = <Runtime as pallet_bridge_parachains::Config<
304 ParachainsInstance,
305 >>::WeightInfo::expected_extra_storage_proof_size()
306 .saturating_add(Para::MAX_HEADER_SIZE);
307
308 let transaction_size = base_tx_size.saturating_add(tx_call_size);
310 let transaction_weight = <Runtime as pallet_bridge_parachains::Config<
311 ParachainsInstance,
312 >>::WeightInfo::submit_parachain_heads_weight(
313 Runtime::DbWeight::get(),
314 &PreComputedSize(transaction_size as _),
315 1,
317 );
318
319 pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::get_priority(
320 &DispatchInfo {
321 call_weight: transaction_weight,
322 extension_weight: Default::default(),
323 class: DispatchClass::Normal,
324 pays_fee: Pays::Yes,
325 },
326 transaction_size as _,
327 tip,
328 Zero::zero(),
329 )
330 }
331 }
332
333 pub mod per_message {
335 use super::*;
336
337 use bp_messages::ChainWithMessages;
338 use pallet_bridge_messages::WeightInfoExt;
339
340 pub fn ensure_priority_boost_is_sane<Runtime, MessagesInstance, PriorityBoostPerMessage>(
348 tip_boost_per_message: BalanceOf<Runtime>,
349 ) where
350 Runtime: pallet_transaction_payment::Config
351 + pallet_bridge_messages::Config<MessagesInstance>,
352 MessagesInstance: 'static,
353 PriorityBoostPerMessage: Get<TransactionPriority>,
354 Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
355 BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
356 {
357 let maximal_messages_in_delivery_transaction =
358 Runtime::BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX;
359 super::ensure_priority_boost_is_sane::<PriorityBoostPerMessage, BalanceOf<Runtime>>(
360 "PriorityBoostPerMessage",
361 maximal_messages_in_delivery_transaction,
362 tip_boost_per_message,
363 |n_messages, tip| {
364 estimate_message_delivery_transaction_priority::<Runtime, MessagesInstance>(
365 n_messages, tip,
366 )
367 },
368 );
369 }
370
371 #[cfg(feature = "integrity-test")]
373 fn estimate_message_delivery_transaction_priority<Runtime, MessagesInstance>(
374 messages: MessageNonce,
375 tip: BalanceOf<Runtime>,
376 ) -> TransactionPriority
377 where
378 Runtime: pallet_transaction_payment::Config
379 + pallet_bridge_messages::Config<MessagesInstance>,
380 MessagesInstance: 'static,
381 Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
382 BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
383 {
384 let base_tx_size = 512;
388 let estimated_message_size = 512;
391 let estimated_message_dispatch_weight = <Runtime as pallet_bridge_messages::Config<
393 MessagesInstance,
394 >>::WeightInfo::message_dispatch_weight(
395 estimated_message_size
396 );
397 let messages_proof_size = <Runtime as pallet_bridge_messages::Config<
401 MessagesInstance,
402 >>::WeightInfo::expected_extra_storage_proof_size()
403 .saturating_mul(2)
404 .saturating_div(3)
405 .saturating_add(estimated_message_size)
406 .saturating_mul(messages as _);
407
408 let transaction_size = base_tx_size.saturating_add(messages_proof_size);
410 let transaction_weight = <Runtime as pallet_bridge_messages::Config<
411 MessagesInstance,
412 >>::WeightInfo::receive_messages_proof_weight(
413 &PreComputedSize(transaction_size as _),
414 messages as _,
415 estimated_message_dispatch_weight.saturating_mul(messages),
416 );
417
418 pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::get_priority(
419 &DispatchInfo {
420 call_weight: transaction_weight,
421 extension_weight: Default::default(),
422 class: DispatchClass::Normal,
423 pays_fee: Pays::Yes,
424 },
425 transaction_size as _,
426 tip,
427 Zero::zero(),
428 )
429 }
430 }
431}