@@ -27,7 +27,7 @@ use bp_messages::{
27
27
LaneId , MessageNonce ,
28
28
} ;
29
29
use bp_runtime:: messages:: MessageDispatchResult ;
30
- use bp_xcm_bridge_hub_router:: LocalXcmChannel ;
30
+ use bp_xcm_bridge_hub_router:: XcmChannelStatusProvider ;
31
31
use codec:: { Decode , Encode } ;
32
32
use frame_support:: { dispatch:: Weight , traits:: Get , CloneNoBound , EqNoBound , PartialEqNoBound } ;
33
33
use frame_system:: Config as SystemConfig ;
@@ -59,8 +59,11 @@ pub struct XcmBlobMessageDispatch<DispatchBlob, Weights, Channel> {
59
59
_marker : sp_std:: marker:: PhantomData < ( DispatchBlob , Weights , Channel ) > ,
60
60
}
61
61
62
- impl < BlobDispatcher : DispatchBlob , Weights : MessagesPalletWeights , Channel : LocalXcmChannel >
63
- MessageDispatch for XcmBlobMessageDispatch < BlobDispatcher , Weights , Channel >
62
+ impl <
63
+ BlobDispatcher : DispatchBlob ,
64
+ Weights : MessagesPalletWeights ,
65
+ Channel : XcmChannelStatusProvider ,
66
+ > MessageDispatch for XcmBlobMessageDispatch < BlobDispatcher , Weights , Channel >
64
67
{
65
68
type DispatchPayload = XcmAsPlainPayload ;
66
69
type DispatchLevelResult = XcmBlobMessageDispatchResult ;
@@ -145,22 +148,23 @@ pub trait XcmBlobHauler {
145
148
/// Returns lane used by this hauler.
146
149
type SenderAndLane : Get < SenderAndLane > ;
147
150
148
- /// Actual XCM message sender (`HRMP` or `UMP`) to the sending chain
151
+ /// Actual XCM message sender (`HRMP` or `UMP`) to the source chain
149
152
/// location (`Self::SenderAndLane::get().location`).
150
- type ToSendingChainSender : SendXcm ;
153
+ type ToSourceChainSender : SendXcm ;
151
154
/// An XCM message that is sent to the sending chain when the bridge queue becomes congested.
152
155
type CongestedMessage : Get < Xcm < ( ) > > ;
153
- /// An XCM message that is sent to the sending chain when the bridge queue becomes uncongested.
156
+ /// An XCM message that is sent to the sending chain when the bridge queue becomes not
157
+ /// congested.
154
158
type UncongestedMessage : Get < Xcm < ( ) > > ;
155
159
156
- /// Runtime message sender origin, which is used by [`Self::MessageSender`] .
160
+ /// Runtime message sender origin, which is used by the associated messages pallet .
157
161
type MessageSenderOrigin ;
158
162
/// Runtime origin for our (i.e. this bridge hub) location within the Consensus Universe.
159
163
fn message_sender_origin ( ) -> Self :: MessageSenderOrigin ;
160
164
}
161
165
162
- /// XCM bridge adapter which connects [`XcmBlobHauler`] with [`XcmBlobHauler::MessageSender `] and
163
- /// makes sure that XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed.
166
+ /// XCM bridge adapter which connects [`XcmBlobHauler`] with [`pallet_bridge_messages `] and
167
+ /// makes sure that XCM blob is sent to the outbound lane to be relayed.
164
168
///
165
169
/// It needs to be used at the source bridge hub.
166
170
pub struct XcmBlobHaulerAdapter < XcmBlobHauler > ( sp_std:: marker:: PhantomData < XcmBlobHauler > ) ;
@@ -233,7 +237,7 @@ pub struct LocalXcmQueueManager<H>(PhantomData<H>);
233
237
const OUTBOUND_LANE_CONGESTED_THRESHOLD : MessageNonce = 8_192 ;
234
238
235
239
/// After we have sent "congestion" XCM message to the sending chain, we wait until number
236
- /// of messages in the outbound bridge queue drops to this count, before sending " uncongestion"
240
+ /// of messages in the outbound bridge queue drops to this count, before sending ` uncongestion`
237
241
/// XCM message.
238
242
const OUTBOUND_LANE_UNCONGESTED_THRESHOLD : MessageNonce = 1_024 ;
239
243
@@ -243,8 +247,7 @@ impl<H: XcmBlobHauler> LocalXcmQueueManager<H> {
243
247
sender_and_lane : & SenderAndLane ,
244
248
enqueued_messages : MessageNonce ,
245
249
) {
246
- // if we have alsender_and_laneready sent the congestion signal, we don't want to do
247
- // anything
250
+ // if we have already sent the congestion signal, we don't want to do anything
248
251
if Self :: is_congested_signal_sent ( sender_and_lane. lane ) {
249
252
return
250
253
}
@@ -311,28 +314,182 @@ impl<H: XcmBlobHauler> LocalXcmQueueManager<H> {
311
314
312
315
/// Returns true if we have sent "congested" signal to the `sending_chain_location`.
313
316
fn is_congested_signal_sent ( lane : LaneId ) -> bool {
314
- OutboundLanesCongestedSignals :: < H :: Runtime , H :: MessagesInstance > :: get ( & lane)
317
+ OutboundLanesCongestedSignals :: < H :: Runtime , H :: MessagesInstance > :: get ( lane)
315
318
}
316
319
317
320
/// Send congested signal to the `sending_chain_location`.
318
321
fn send_congested_signal ( sender_and_lane : & SenderAndLane ) -> Result < ( ) , SendError > {
319
- send_xcm :: < H :: ToSendingChainSender > ( sender_and_lane. location , H :: CongestedMessage :: get ( ) ) ?;
322
+ send_xcm :: < H :: ToSourceChainSender > ( sender_and_lane. location , H :: CongestedMessage :: get ( ) ) ?;
320
323
OutboundLanesCongestedSignals :: < H :: Runtime , H :: MessagesInstance > :: insert (
321
324
sender_and_lane. lane ,
322
325
true ,
323
326
) ;
324
327
Ok ( ( ) )
325
328
}
326
329
327
- /// Send uncongested signal to the `sending_chain_location`.
330
+ /// Send ` uncongested` signal to the `sending_chain_location`.
328
331
fn send_uncongested_signal ( sender_and_lane : & SenderAndLane ) -> Result < ( ) , SendError > {
329
- send_xcm :: < H :: ToSendingChainSender > (
330
- sender_and_lane. location ,
331
- H :: UncongestedMessage :: get ( ) ,
332
- ) ?;
332
+ send_xcm :: < H :: ToSourceChainSender > ( sender_and_lane. location , H :: UncongestedMessage :: get ( ) ) ?;
333
333
OutboundLanesCongestedSignals :: < H :: Runtime , H :: MessagesInstance > :: remove (
334
- & sender_and_lane. lane ,
334
+ sender_and_lane. lane ,
335
335
) ;
336
336
Ok ( ( ) )
337
337
}
338
338
}
339
+
340
+ #[ cfg( test) ]
341
+ mod tests {
342
+ use super :: * ;
343
+ use crate :: mock:: * ;
344
+
345
+ use bp_messages:: OutboundLaneData ;
346
+ use frame_support:: parameter_types;
347
+ use pallet_bridge_messages:: OutboundLanes ;
348
+
349
+ parameter_types ! {
350
+ pub TestSenderAndLane : SenderAndLane = SenderAndLane {
351
+ location: MultiLocation :: new( 1 , X1 ( Parachain ( 1000 ) ) ) ,
352
+ lane: TEST_LANE_ID ,
353
+ } ;
354
+ pub DummyXcmMessage : Xcm <( ) > = Xcm :: new( ) ;
355
+ }
356
+
357
+ struct DummySendXcm ;
358
+
359
+ impl DummySendXcm {
360
+ fn messages_sent ( ) -> u32 {
361
+ frame_support:: storage:: unhashed:: get ( b"DummySendXcm" ) . unwrap_or ( 0 )
362
+ }
363
+ }
364
+
365
+ impl SendXcm for DummySendXcm {
366
+ type Ticket = ( ) ;
367
+
368
+ fn validate (
369
+ _destination : & mut Option < MultiLocation > ,
370
+ _message : & mut Option < Xcm < ( ) > > ,
371
+ ) -> SendResult < Self :: Ticket > {
372
+ Ok ( ( ( ) , Default :: default ( ) ) )
373
+ }
374
+
375
+ fn deliver ( _ticket : Self :: Ticket ) -> Result < XcmHash , SendError > {
376
+ let messages_sent: u32 = Self :: messages_sent ( ) ;
377
+ frame_support:: storage:: unhashed:: put ( b"DummySendXcm" , & ( messages_sent + 1 ) ) ;
378
+ Ok ( XcmHash :: default ( ) )
379
+ }
380
+ }
381
+
382
+ struct TestBlobHauler ;
383
+
384
+ impl XcmBlobHauler for TestBlobHauler {
385
+ type Runtime = TestRuntime ;
386
+ type MessagesInstance = ( ) ;
387
+ type SenderAndLane = TestSenderAndLane ;
388
+
389
+ type ToSourceChainSender = DummySendXcm ;
390
+ type CongestedMessage = DummyXcmMessage ;
391
+ type UncongestedMessage = DummyXcmMessage ;
392
+
393
+ type MessageSenderOrigin = RuntimeOrigin ;
394
+
395
+ fn message_sender_origin ( ) -> Self :: MessageSenderOrigin {
396
+ RuntimeOrigin :: root ( )
397
+ }
398
+ }
399
+
400
+ type TestBlobHaulerAdapter = XcmBlobHaulerAdapter < TestBlobHauler > ;
401
+
402
+ fn fill_up_lane_to_congestion ( ) {
403
+ OutboundLanes :: < TestRuntime , ( ) > :: insert (
404
+ TEST_LANE_ID ,
405
+ OutboundLaneData {
406
+ oldest_unpruned_nonce : 0 ,
407
+ latest_received_nonce : 0 ,
408
+ latest_generated_nonce : OUTBOUND_LANE_CONGESTED_THRESHOLD ,
409
+ } ,
410
+ ) ;
411
+ }
412
+
413
+ #[ test]
414
+ fn congested_signal_is_not_sent_twice ( ) {
415
+ run_test ( || {
416
+ fill_up_lane_to_congestion ( ) ;
417
+
418
+ // next sent message leads to congested signal
419
+ TestBlobHaulerAdapter :: haul_blob ( vec ! [ 42 ] ) . unwrap ( ) ;
420
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
421
+
422
+ // next sent message => we don't sent another congested signal
423
+ TestBlobHaulerAdapter :: haul_blob ( vec ! [ 42 ] ) . unwrap ( ) ;
424
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
425
+ } ) ;
426
+ }
427
+
428
+ #[ test]
429
+ fn congested_signal_is_not_sent_when_outbound_lane_is_not_congested ( ) {
430
+ run_test ( || {
431
+ TestBlobHaulerAdapter :: haul_blob ( vec ! [ 42 ] ) . unwrap ( ) ;
432
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 0 ) ;
433
+ } ) ;
434
+ }
435
+
436
+ #[ test]
437
+ fn congested_signal_is_sent_when_outbound_lane_is_congested ( ) {
438
+ run_test ( || {
439
+ fill_up_lane_to_congestion ( ) ;
440
+
441
+ // next sent message leads to congested signal
442
+ TestBlobHaulerAdapter :: haul_blob ( vec ! [ 42 ] ) . unwrap ( ) ;
443
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
444
+ assert ! ( LocalXcmQueueManager :: <TestBlobHauler >:: is_congested_signal_sent( TEST_LANE_ID ) ) ;
445
+ } ) ;
446
+ }
447
+
448
+ #[ test]
449
+ fn uncongested_signal_is_not_sent_when_messages_are_delivered_at_other_lane ( ) {
450
+ run_test ( || {
451
+ LocalXcmQueueManager :: < TestBlobHauler > :: send_congested_signal ( & TestSenderAndLane :: get ( ) ) . unwrap ( ) ;
452
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
453
+
454
+ // when we receive a delivery report for other lane, we don't send an uncongested signal
455
+ TestBlobHaulerAdapter :: on_messages_delivered ( LaneId ( [ 42 , 42 , 42 , 42 ] ) , 0 ) ;
456
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
457
+ } ) ;
458
+ }
459
+
460
+ #[ test]
461
+ fn uncongested_signal_is_not_sent_when_we_havent_send_congested_signal_before ( ) {
462
+ run_test ( || {
463
+ TestBlobHaulerAdapter :: on_messages_delivered ( TEST_LANE_ID , 0 ) ;
464
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 0 ) ;
465
+ } ) ;
466
+ }
467
+
468
+ #[ test]
469
+ fn uncongested_signal_is_not_sent_if_outbound_lane_is_still_congested ( ) {
470
+ run_test ( || {
471
+ LocalXcmQueueManager :: < TestBlobHauler > :: send_congested_signal ( & TestSenderAndLane :: get ( ) ) . unwrap ( ) ;
472
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
473
+
474
+ TestBlobHaulerAdapter :: on_messages_delivered (
475
+ TEST_LANE_ID ,
476
+ OUTBOUND_LANE_UNCONGESTED_THRESHOLD + 1 ,
477
+ ) ;
478
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
479
+ } ) ;
480
+ }
481
+
482
+ #[ test]
483
+ fn uncongested_signal_is_sent_if_outbound_lane_is_uncongested ( ) {
484
+ run_test ( || {
485
+ LocalXcmQueueManager :: < TestBlobHauler > :: send_congested_signal ( & TestSenderAndLane :: get ( ) ) . unwrap ( ) ;
486
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 1 ) ;
487
+
488
+ TestBlobHaulerAdapter :: on_messages_delivered (
489
+ TEST_LANE_ID ,
490
+ OUTBOUND_LANE_UNCONGESTED_THRESHOLD ,
491
+ ) ;
492
+ assert_eq ! ( DummySendXcm :: messages_sent( ) , 2 ) ;
493
+ } ) ;
494
+ }
495
+ }
0 commit comments