@@ -25,7 +25,9 @@ use crate::{
25
25
26
26
use async_std:: sync:: Arc ;
27
27
use bp_messages:: { LaneId , MessageNonce } ;
28
- use bp_runtime:: { AccountIdOf , Chain as _, HeaderIdOf , WeightExtraOps } ;
28
+ use bp_runtime:: {
29
+ AccountIdOf , Chain as _, EncodedOrDecodedCall , HeaderIdOf , TransactionEra , WeightExtraOps ,
30
+ } ;
29
31
use bridge_runtime_common:: messages:: {
30
32
source:: FromBridgedChainMessagesDeliveryProof , target:: FromBridgedChainMessagesProof ,
31
33
} ;
@@ -35,13 +37,15 @@ use messages_relay::{message_lane::MessageLane, message_lane_loop::BatchTransact
35
37
use pallet_bridge_messages:: { Call as BridgeMessagesCall , Config as BridgeMessagesConfig } ;
36
38
use relay_substrate_client:: {
37
39
transaction_stall_timeout, AccountKeyPairOf , BalanceOf , BlockNumberOf , CallOf , Chain ,
38
- ChainWithMessages , ChainWithTransactions , Client , Error as SubstrateError , HashOf ,
40
+ ChainWithMessages , ChainWithTransactions , Client , Error as SubstrateError , HashOf , SignParam ,
41
+ UnsignedTransaction ,
39
42
} ;
40
43
use relay_utils:: {
41
44
metrics:: { GlobalMetrics , MetricsParams , StandaloneMetric } ,
42
45
STALL_TIMEOUT ,
43
46
} ;
44
47
use sp_core:: Pair ;
48
+ use sp_runtime:: traits:: Zero ;
45
49
use std:: { convert:: TryFrom , fmt:: Debug , marker:: PhantomData } ;
46
50
47
51
/// Substrate -> Substrate messages synchronization pipeline.
@@ -159,25 +163,25 @@ where
159
163
AccountIdOf < P :: TargetChain > : From < <AccountKeyPairOf < P :: TargetChain > as Pair >:: Public > ,
160
164
BalanceOf < P :: SourceChain > : TryFrom < BalanceOf < P :: TargetChain > > ,
161
165
{
162
- let source_client = params. source_client ;
163
- let target_client = params. target_client ;
164
- let relayer_id_at_source: AccountIdOf < P :: SourceChain > =
165
- params. source_transaction_params . signer . public ( ) . into ( ) ;
166
-
167
166
// 2/3 is reserved for proofs and tx overhead
168
167
let max_messages_size_in_single_batch = P :: TargetChain :: max_extrinsic_size ( ) / 3 ;
169
168
// we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using
170
169
// weights from Rialto and then simply dividing it by x2.
171
170
let ( max_messages_in_single_batch, max_messages_weight_in_single_batch) =
172
- crate :: messages_lane:: select_delivery_transaction_limits :: <
173
- <P :: TargetChain as ChainWithMessages >:: WeightInfo ,
174
- > (
171
+ select_delivery_transaction_limits_rpc :: < P > (
172
+ & params,
175
173
P :: TargetChain :: max_extrinsic_weight ( ) ,
176
174
P :: SourceChain :: MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX ,
177
- ) ;
175
+ )
176
+ . await ?;
178
177
let ( max_messages_in_single_batch, max_messages_weight_in_single_batch) =
179
178
( max_messages_in_single_batch / 2 , max_messages_weight_in_single_batch / 2 ) ;
180
179
180
+ let source_client = params. source_client ;
181
+ let target_client = params. target_client ;
182
+ let relayer_id_at_source: AccountIdOf < P :: SourceChain > =
183
+ params. source_transaction_params . signer . public ( ) . into ( ) ;
184
+
181
185
log:: info!(
182
186
target: "bridge" ,
183
187
"Starting {} -> {} messages relay.\n \t \
@@ -437,12 +441,15 @@ macro_rules! generate_receive_message_delivery_proof_call_builder {
437
441
} ;
438
442
}
439
443
440
- /// Returns maximal number of messages and their maximal cumulative dispatch weight, based
441
- /// on given chain parameters.
442
- pub fn select_delivery_transaction_limits < W : pallet_bridge_messages :: WeightInfoExt > (
444
+ /// Returns maximal number of messages and their maximal cumulative dispatch weight.
445
+ async fn select_delivery_transaction_limits_rpc < P : SubstrateMessageLane > (
446
+ params : & MessagesRelayParams < P > ,
443
447
max_extrinsic_weight : Weight ,
444
448
max_unconfirmed_messages_at_inbound_lane : MessageNonce ,
445
- ) -> ( MessageNonce , Weight ) {
449
+ ) -> anyhow:: Result < ( MessageNonce , Weight ) >
450
+ where
451
+ AccountIdOf < P :: SourceChain > : From < <AccountKeyPairOf < P :: SourceChain > as Pair >:: Public > ,
452
+ {
446
453
// We may try to guess accurate value, based on maximal number of messages and per-message
447
454
// weight overhead, but the relay loop isn't using this info in a super-accurate way anyway.
448
455
// So just a rough guess: let's say 1/3 of max tx weight is for tx itself and the rest is
@@ -455,13 +462,35 @@ pub fn select_delivery_transaction_limits<W: pallet_bridge_messages::WeightInfoE
455
462
let weight_for_delivery_tx = max_extrinsic_weight / 3 ;
456
463
let weight_for_messages_dispatch = max_extrinsic_weight - weight_for_delivery_tx;
457
464
458
- let delivery_tx_base_weight = W :: receive_messages_proof_overhead ( ) +
459
- W :: receive_messages_proof_outbound_lane_state_overhead ( ) ;
460
- let delivery_tx_weight_rest = weight_for_delivery_tx - delivery_tx_base_weight;
465
+ // weight of empty message delivery with outbound lane state
466
+ let delivery_tx_with_zero_messages = dummy_messages_delivery_transaction :: < P > ( params, 0 ) ?;
467
+ let delivery_tx_with_zero_messages_weight = params
468
+ . target_client
469
+ . extimate_extrinsic_weight ( delivery_tx_with_zero_messages)
470
+ . await
471
+ . map_err ( |e| {
472
+ anyhow:: format_err!( "Failed to estimate delivery extrinsic weight: {:?}" , e)
473
+ } ) ?;
474
+
475
+ // weight of single message delivery with outbound lane state
476
+ let delivery_tx_with_one_message = dummy_messages_delivery_transaction :: < P > ( params, 1 ) ?;
477
+ let delivery_tx_with_one_message_weight = params
478
+ . target_client
479
+ . extimate_extrinsic_weight ( delivery_tx_with_one_message)
480
+ . await
481
+ . map_err ( |e| {
482
+ anyhow:: format_err!( "Failed to estimate delivery extrinsic weight: {:?}" , e)
483
+ } ) ?;
484
+
485
+ // message overhead is roughly `delivery_tx_with_one_message_weight -
486
+ // delivery_tx_with_zero_messages_weight`
487
+ let delivery_tx_weight_rest = weight_for_delivery_tx - delivery_tx_with_zero_messages_weight;
488
+ let delivery_tx_message_overhead =
489
+ delivery_tx_with_one_message_weight. saturating_sub ( delivery_tx_with_zero_messages_weight) ;
461
490
462
491
let max_number_of_messages = std:: cmp:: min (
463
492
delivery_tx_weight_rest
464
- . min_components_checked_div ( W :: receive_messages_proof_messages_overhead ( 1 ) )
493
+ . min_components_checked_div ( delivery_tx_message_overhead )
465
494
. unwrap_or ( u64:: MAX ) ,
466
495
max_unconfirmed_messages_at_inbound_lane,
467
496
) ;
@@ -475,36 +504,58 @@ pub fn select_delivery_transaction_limits<W: pallet_bridge_messages::WeightInfoE
475
504
"Relay shall be able to deliver messages with dispatch weight = max_extrinsic_weight / 2" ,
476
505
) ;
477
506
478
- ( max_number_of_messages, weight_for_messages_dispatch)
507
+ Ok ( ( max_number_of_messages, weight_for_messages_dispatch) )
479
508
}
480
509
481
- #[ cfg( test) ]
482
- mod tests {
483
- use super :: * ;
484
- use bp_runtime:: Chain ;
485
-
486
- type RialtoToMillauMessagesWeights =
487
- pallet_bridge_messages:: weights:: BridgeWeight < rialto_runtime:: Runtime > ;
488
-
489
- #[ test]
490
- fn select_delivery_transaction_limits_is_sane ( ) {
491
- // we want to check the `proof_size` component here too. But for Rialto and Millau
492
- // it is set to `u64::MAX` (as for Polkadot and other relay/standalone chains).
493
- // So let's use RialtoParachain limits here - it has `proof_size` limit as all
494
- // Cumulus-based parachains do.
495
- let ( max_count, max_weight) =
496
- select_delivery_transaction_limits :: < RialtoToMillauMessagesWeights > (
497
- bp_rialto_parachain:: RialtoParachain :: max_extrinsic_weight ( ) ,
498
- bp_rialto:: MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX ,
499
- ) ;
500
- assert_eq ! (
501
- ( max_count, max_weight) ,
502
- // We don't actually care about these values, so feel free to update them whenever test
503
- // fails. The only thing to do before that is to ensure that new values looks sane:
504
- // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages.
505
- //
506
- // Any significant change in this values should attract additional attention.
507
- ( 1024 , Weight :: from_parts( 866_600_106_667 , 2_271_915 ) ) ,
510
+ /// Returns dummy message delivery transaction with zero messages and `1kb` proof.
511
+ fn dummy_messages_delivery_transaction < P : SubstrateMessageLane > (
512
+ params : & MessagesRelayParams < P > ,
513
+ messages : u32 ,
514
+ ) -> anyhow:: Result < <P :: TargetChain as ChainWithTransactions >:: SignedTransaction >
515
+ where
516
+ AccountIdOf < P :: SourceChain > : From < <AccountKeyPairOf < P :: SourceChain > as Pair >:: Public > ,
517
+ {
518
+ // we don't care about any call values here, because all that the estimation RPC does
519
+ // is calls `GetDispatchInfo::get_dispatch_info` for the wrapped call. So we only are
520
+ // interested in values that affect call weight - e.g. number of messages and the
521
+ // storage proof size
522
+
523
+ let dummy_messages_delivery_call =
524
+ P :: ReceiveMessagesProofCallBuilder :: build_receive_messages_proof_call (
525
+ params. source_transaction_params . signer . public ( ) . into ( ) ,
526
+ (
527
+ Weight :: zero ( ) ,
528
+ FromBridgedChainMessagesProof {
529
+ bridged_header_hash : Default :: default ( ) ,
530
+ // we may use per-chain `EXTRA_STORAGE_PROOF_SIZE`, but since we don't need
531
+ // exact values, this global estimation is fine
532
+ storage_proof : vec ! [ vec![
533
+ 42u8 ;
534
+ pallet_bridge_messages:: EXTRA_STORAGE_PROOF_SIZE
535
+ as usize
536
+ ] ] ,
537
+ lane : Default :: default ( ) ,
538
+ nonces_start : 1 ,
539
+ nonces_end : messages as u64 ,
540
+ } ,
541
+ ) ,
542
+ messages,
543
+ Weight :: zero ( ) ,
544
+ false ,
508
545
) ;
509
- }
546
+ P :: TargetChain :: sign_transaction (
547
+ SignParam {
548
+ spec_version : 0 ,
549
+ transaction_version : 0 ,
550
+ genesis_hash : Default :: default ( ) ,
551
+ signer : params. target_transaction_params . signer . clone ( ) ,
552
+ } ,
553
+ UnsignedTransaction {
554
+ call : EncodedOrDecodedCall :: Decoded ( dummy_messages_delivery_call) ,
555
+ nonce : Zero :: zero ( ) ,
556
+ tip : Zero :: zero ( ) ,
557
+ era : TransactionEra :: Immortal ,
558
+ } ,
559
+ )
560
+ . map_err ( Into :: into)
510
561
}
0 commit comments