1use crate::weights::WeightInfo;
20
21use bp_messages::{MessageNonce, UnrewardedRelayersState};
22use bp_runtime::{PreComputedSize, Size};
23use frame_support::weights::Weight;
24
25pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128;
27
28const SIGNED_EXTENSIONS_SIZE: u32 = 1024;
31
32pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024;
36
37pub fn ensure_weights_are_correct<W: WeightInfoExt>() {
39 assert_eq!(W::receive_messages_proof_outbound_lane_state_overhead().proof_size(), 0);
47 assert_ne!(W::storage_proof_size_overhead(1).ref_time(), 0);
48 assert_eq!(W::storage_proof_size_overhead(1).proof_size(), 0);
49
50 assert_ne!(W::receive_messages_delivery_proof_overhead().ref_time(), 0);
52 assert_ne!(W::receive_messages_delivery_proof_overhead().proof_size(), 0);
53 assert_eq!(W::receive_messages_delivery_proof_messages_overhead(1).proof_size(), 0);
56 assert_ne!(W::storage_proof_size_overhead(1).ref_time(), 0);
61 assert_eq!(W::storage_proof_size_overhead(1).proof_size(), 0);
62
63 let receive_messages_proof_weight =
65 W::receive_messages_proof_weight(&PreComputedSize(1), 10, Weight::zero());
66 assert_ne!(receive_messages_proof_weight.ref_time(), 0);
67 assert_ne!(receive_messages_proof_weight.proof_size(), 0);
68 messages_proof_size_does_not_affect_proof_size::<W>();
69 messages_count_does_not_affect_proof_size::<W>();
70
71 let receive_messages_delivery_proof_weight = W::receive_messages_delivery_proof_weight(
73 &PreComputedSize(1),
74 &UnrewardedRelayersState::default(),
75 );
76 assert_ne!(receive_messages_delivery_proof_weight.ref_time(), 0);
77 assert_ne!(receive_messages_delivery_proof_weight.proof_size(), 0);
78 messages_delivery_proof_size_does_not_affect_proof_size::<W>();
79 total_messages_in_delivery_proof_does_not_affect_proof_size::<W>();
80}
81
82pub fn ensure_maximal_message_dispatch<W: WeightInfoExt>(
84 max_incoming_message_size: u32,
85 max_incoming_message_dispatch_weight: Weight,
86) {
87 let message_dispatch_weight = W::message_dispatch_weight(max_incoming_message_size);
88 assert!(
89 message_dispatch_weight.all_lte(max_incoming_message_dispatch_weight),
90 "Dispatch weight of maximal message {message_dispatch_weight:?} must be lower \
91 than the hardcoded {max_incoming_message_dispatch_weight:?}",
92 );
93}
94
95pub fn ensure_able_to_receive_message<W: WeightInfoExt>(
97 max_extrinsic_size: u32,
98 max_extrinsic_weight: Weight,
99 max_incoming_message_proof_size: u32,
100 max_incoming_message_dispatch_weight: Weight,
101) {
102 let max_delivery_transaction_size =
104 max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE);
105 assert!(
106 max_delivery_transaction_size <= max_extrinsic_size,
107 "Size of maximal message delivery transaction {max_incoming_message_proof_size} + \
108 {SIGNED_EXTENSIONS_SIZE} is larger than maximal possible transaction size {max_extrinsic_size}",
109 );
110
111 let max_delivery_transaction_dispatch_weight = W::receive_messages_proof_weight(
113 &PreComputedSize(
114 (max_incoming_message_proof_size + W::expected_extra_storage_proof_size()) as usize,
115 ),
116 1,
117 max_incoming_message_dispatch_weight,
118 );
119 assert!(
120 max_delivery_transaction_dispatch_weight.all_lte(max_extrinsic_weight),
121 "Weight of maximal message delivery transaction + {max_delivery_transaction_dispatch_weight} is larger than maximal possible transaction weight {max_extrinsic_weight}",
122 );
123}
124
125pub fn ensure_able_to_receive_confirmation<W: WeightInfoExt>(
127 max_extrinsic_size: u32,
128 max_extrinsic_weight: Weight,
129 max_inbound_lane_data_proof_size_from_peer_chain: u32,
130 max_unrewarded_relayer_entries_at_peer_inbound_lane: MessageNonce,
131 max_unconfirmed_messages_at_inbound_lane: MessageNonce,
132) {
133 let max_confirmation_transaction_size =
135 max_inbound_lane_data_proof_size_from_peer_chain.saturating_add(SIGNED_EXTENSIONS_SIZE);
136 assert!(
137 max_confirmation_transaction_size <= max_extrinsic_size,
138 "Size of maximal message delivery confirmation transaction {max_inbound_lane_data_proof_size_from_peer_chain} + {SIGNED_EXTENSIONS_SIZE} is larger than maximal possible transaction size {max_extrinsic_size}",
139 );
140
141 let max_confirmation_transaction_dispatch_weight = W::receive_messages_delivery_proof_weight(
144 &PreComputedSize(max_inbound_lane_data_proof_size_from_peer_chain as usize),
145 &UnrewardedRelayersState {
146 unrewarded_relayer_entries: max_unrewarded_relayer_entries_at_peer_inbound_lane,
147 total_messages: max_unconfirmed_messages_at_inbound_lane,
148 ..Default::default()
149 },
150 );
151 assert!(
152 max_confirmation_transaction_dispatch_weight.all_lte(max_extrinsic_weight),
153 "Weight of maximal confirmation transaction {max_confirmation_transaction_dispatch_weight} is larger than maximal possible transaction weight {max_extrinsic_weight}",
154 );
155}
156
157fn messages_proof_size_does_not_affect_proof_size<W: WeightInfoExt>() {
159 let dispatch_weight = Weight::zero();
160 let weight_when_proof_size_is_8k =
161 W::receive_messages_proof_weight(&PreComputedSize(8 * 1024), 1, dispatch_weight);
162 let weight_when_proof_size_is_16k =
163 W::receive_messages_proof_weight(&PreComputedSize(16 * 1024), 1, dispatch_weight);
164
165 ensure_weight_components_are_not_zero(weight_when_proof_size_is_8k);
166 ensure_weight_components_are_not_zero(weight_when_proof_size_is_16k);
167 ensure_proof_size_is_the_same(
168 weight_when_proof_size_is_8k,
169 weight_when_proof_size_is_16k,
170 "Messages proof size does not affect values that we read from our storage",
171 );
172}
173
174fn messages_count_does_not_affect_proof_size<W: WeightInfoExt>() {
180 let messages_proof_size = PreComputedSize(8 * 1024);
181 let dispatch_weight = Weight::zero();
182 let weight_of_one_incoming_message =
183 W::receive_messages_proof_weight(&messages_proof_size, 1, dispatch_weight);
184 let weight_of_two_incoming_messages =
185 W::receive_messages_proof_weight(&messages_proof_size, 2, dispatch_weight);
186
187 ensure_weight_components_are_not_zero(weight_of_one_incoming_message);
188 ensure_weight_components_are_not_zero(weight_of_two_incoming_messages);
189 ensure_proof_size_is_the_same(
190 weight_of_one_incoming_message,
191 weight_of_two_incoming_messages,
192 "Number of same-lane incoming messages does not affect values that we read from our storage",
193 );
194}
195
196fn messages_delivery_proof_size_does_not_affect_proof_size<W: WeightInfoExt>() {
198 let relayers_state = UnrewardedRelayersState {
199 unrewarded_relayer_entries: 1,
200 messages_in_oldest_entry: 1,
201 total_messages: 1,
202 last_delivered_nonce: 1,
203 };
204 let weight_when_proof_size_is_8k =
205 W::receive_messages_delivery_proof_weight(&PreComputedSize(8 * 1024), &relayers_state);
206 let weight_when_proof_size_is_16k =
207 W::receive_messages_delivery_proof_weight(&PreComputedSize(16 * 1024), &relayers_state);
208
209 ensure_weight_components_are_not_zero(weight_when_proof_size_is_8k);
210 ensure_weight_components_are_not_zero(weight_when_proof_size_is_16k);
211 ensure_proof_size_is_the_same(
212 weight_when_proof_size_is_8k,
213 weight_when_proof_size_is_16k,
214 "Messages delivery proof size does not affect values that we read from our storage",
215 );
216}
217
218fn total_messages_in_delivery_proof_does_not_affect_proof_size<W: WeightInfoExt>() {
221 let proof_size = PreComputedSize(8 * 1024);
222 let weight_when_1k_messages_confirmed = W::receive_messages_delivery_proof_weight(
223 &proof_size,
224 &UnrewardedRelayersState {
225 unrewarded_relayer_entries: 1,
226 messages_in_oldest_entry: 1,
227 total_messages: 1024,
228 last_delivered_nonce: 1,
229 },
230 );
231 let weight_when_2k_messages_confirmed = W::receive_messages_delivery_proof_weight(
232 &proof_size,
233 &UnrewardedRelayersState {
234 unrewarded_relayer_entries: 1,
235 messages_in_oldest_entry: 1,
236 total_messages: 2048,
237 last_delivered_nonce: 1,
238 },
239 );
240
241 ensure_weight_components_are_not_zero(weight_when_1k_messages_confirmed);
242 ensure_weight_components_are_not_zero(weight_when_2k_messages_confirmed);
243 ensure_proof_size_is_the_same(
244 weight_when_1k_messages_confirmed,
245 weight_when_2k_messages_confirmed,
246 "More messages in delivery proof does not affect values that we read from our storage",
247 );
248}
249
250fn ensure_weight_components_are_not_zero(weight: Weight) {
252 assert_ne!(weight.ref_time(), 0);
253 assert_ne!(weight.proof_size(), 0);
254}
255
256fn ensure_proof_size_is_the_same(weight1: Weight, weight2: Weight, msg: &str) {
258 assert_eq!(
259 weight1.proof_size(),
260 weight2.proof_size(),
261 "{msg}: {} must be equal to {}",
262 weight1.proof_size(),
263 weight2.proof_size(),
264 );
265}
266
267pub trait WeightInfoExt: WeightInfo {
269 fn expected_extra_storage_proof_size() -> u32;
276
277 fn receive_messages_proof_overhead_from_runtime() -> Weight;
293
294 fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight;
297
298 fn receive_messages_proof_weight(
302 proof: &impl Size,
303 messages_count: u32,
304 dispatch_weight: Weight,
305 ) -> Weight {
306 let base_weight = Self::receive_n_messages_proof(messages_count);
308 let transaction_overhead_from_runtime =
309 Self::receive_messages_proof_overhead_from_runtime();
310 let outbound_state_delivery_weight =
311 Self::receive_messages_proof_outbound_lane_state_overhead();
312 let messages_dispatch_weight = dispatch_weight;
313
314 let expected_proof_size = EXPECTED_DEFAULT_MESSAGE_LENGTH
316 .saturating_mul(messages_count.saturating_sub(1))
317 .saturating_add(Self::expected_extra_storage_proof_size());
318 let actual_proof_size = proof.size();
319 let proof_size_overhead = Self::storage_proof_size_overhead(
320 actual_proof_size.saturating_sub(expected_proof_size),
321 );
322
323 base_weight
324 .saturating_add(transaction_overhead_from_runtime)
325 .saturating_add(outbound_state_delivery_weight)
326 .saturating_add(messages_dispatch_weight)
327 .saturating_add(proof_size_overhead)
328 }
329
330 fn receive_messages_delivery_proof_weight(
332 proof: &impl Size,
333 relayers_state: &UnrewardedRelayersState,
334 ) -> Weight {
335 let transaction_overhead = Self::receive_messages_delivery_proof_overhead();
337 let transaction_overhead_from_runtime =
338 Self::receive_messages_delivery_proof_overhead_from_runtime();
339 let messages_overhead =
340 Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages);
341 let relayers_overhead = Self::receive_messages_delivery_proof_relayers_overhead(
342 relayers_state.unrewarded_relayer_entries,
343 );
344
345 let expected_proof_size = Self::expected_extra_storage_proof_size();
347 let actual_proof_size = proof.size();
348 let proof_size_overhead = Self::storage_proof_size_overhead(
349 actual_proof_size.saturating_sub(expected_proof_size),
350 );
351
352 transaction_overhead
353 .saturating_add(transaction_overhead_from_runtime)
354 .saturating_add(messages_overhead)
355 .saturating_add(relayers_overhead)
356 .saturating_add(proof_size_overhead)
357 }
358
359 fn receive_messages_proof_outbound_lane_state_overhead() -> Weight {
364 let weight_of_single_message_and_lane_state =
365 Self::receive_single_message_proof_with_outbound_lane_state();
366 let weight_of_single_message = Self::receive_single_message_proof();
367 weight_of_single_message_and_lane_state.saturating_sub(weight_of_single_message)
368 }
369
370 fn receive_messages_delivery_proof_overhead() -> Weight {
373 let weight_of_two_messages_and_two_tx_overheads =
374 Self::receive_delivery_proof_for_single_message().saturating_mul(2);
375 let weight_of_two_messages_and_single_tx_overhead =
376 Self::receive_delivery_proof_for_two_messages_by_single_relayer();
377 weight_of_two_messages_and_two_tx_overheads
378 .saturating_sub(weight_of_two_messages_and_single_tx_overhead)
379 }
380
381 fn receive_messages_delivery_proof_messages_overhead(messages: MessageNonce) -> Weight {
384 let weight_of_two_messages =
385 Self::receive_delivery_proof_for_two_messages_by_single_relayer();
386 let weight_of_single_message = Self::receive_delivery_proof_for_single_message();
387 weight_of_two_messages
388 .saturating_sub(weight_of_single_message)
389 .saturating_mul(messages as _)
390 }
391
392 fn receive_messages_delivery_proof_relayers_overhead(relayers: MessageNonce) -> Weight {
395 let weight_of_two_messages_by_two_relayers =
396 Self::receive_delivery_proof_for_two_messages_by_two_relayers();
397 let weight_of_two_messages_by_single_relayer =
398 Self::receive_delivery_proof_for_two_messages_by_single_relayer();
399 weight_of_two_messages_by_two_relayers
400 .saturating_sub(weight_of_two_messages_by_single_relayer)
401 .saturating_mul(relayers as _)
402 }
403
404 fn storage_proof_size_overhead(proof_size: u32) -> Weight {
413 let proof_size_in_bytes = proof_size;
414 let byte_weight = Self::receive_single_n_bytes_message_proof(2) -
415 Self::receive_single_n_bytes_message_proof(1);
416 proof_size_in_bytes * byte_weight
417 }
418
419 fn message_dispatch_weight(message_size: u32) -> Weight {
427 let message_size_in_bytes = message_size;
428 Self::receive_single_n_bytes_message_proof_with_dispatch(message_size_in_bytes)
429 .saturating_sub(Self::receive_single_n_bytes_message_proof(message_size_in_bytes))
430 }
431}
432
433impl WeightInfoExt for () {
434 fn expected_extra_storage_proof_size() -> u32 {
435 EXTRA_STORAGE_PROOF_SIZE
436 }
437
438 fn receive_messages_proof_overhead_from_runtime() -> Weight {
439 Weight::zero()
440 }
441
442 fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
443 Weight::zero()
444 }
445}
446
447impl<T: frame_system::Config> WeightInfoExt for crate::weights::BridgeWeight<T> {
448 fn expected_extra_storage_proof_size() -> u32 {
449 EXTRA_STORAGE_PROOF_SIZE
450 }
451
452 fn receive_messages_proof_overhead_from_runtime() -> Weight {
453 Weight::zero()
454 }
455
456 fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight {
457 Weight::zero()
458 }
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464 use crate::{tests::mock::TestRuntime, weights::BridgeWeight};
465
466 #[test]
467 fn ensure_default_weights_are_correct() {
468 ensure_weights_are_correct::<BridgeWeight<TestRuntime>>();
469 }
470}