2
2
3
3
mod common;
4
4
5
- use common:: { create_service_and_client_nodes, get_lsps_message, Node } ;
5
+ use common:: create_service_and_client_nodes;
6
+ use common:: { get_lsps_message, Node } ;
6
7
7
8
use lightning_liquidity:: events:: LiquidityEvent ;
8
9
use lightning_liquidity:: lsps0:: ser:: LSPSDateTime ;
9
10
use lightning_liquidity:: lsps2:: client:: LSPS2ClientConfig ;
10
- use lightning_liquidity:: lsps2:: event:: { LSPS2ClientEvent , LSPS2ServiceEvent } ;
11
+ use lightning_liquidity:: lsps2:: event:: LSPS2ClientEvent ;
12
+ use lightning_liquidity:: lsps2:: event:: LSPS2ServiceEvent ;
11
13
use lightning_liquidity:: lsps2:: msgs:: LSPS2RawOpeningFeeParams ;
12
14
use lightning_liquidity:: lsps2:: service:: LSPS2ServiceConfig ;
13
15
use lightning_liquidity:: lsps2:: utils:: is_valid_opening_fee_params;
@@ -31,6 +33,9 @@ use bitcoin::Network;
31
33
use std:: str:: FromStr ;
32
34
use std:: time:: Duration ;
33
35
36
+ const MAX_PENDING_REQUESTS_PER_PEER : usize = 10 ;
37
+ const MAX_TOTAL_PENDING_REQUESTS : usize = 1000 ;
38
+
34
39
fn setup_test_lsps2 (
35
40
) -> ( bitcoin:: secp256k1:: PublicKey , bitcoin:: secp256k1:: PublicKey , Node , Node , [ u8 ; 32 ] ) {
36
41
let promise_secret = [ 42 ; 32 ] ;
@@ -258,12 +263,9 @@ fn channel_open_failed() {
258
263
let ( service_node_id, client_node_id, service_node, client_node, _) = setup_test_lsps2 ( ) ;
259
264
260
265
let service_handler = service_node. liquidity_manager . lsps2_service_handler ( ) . unwrap ( ) ;
266
+ let client_handler = client_node. liquidity_manager . lsps2_client_handler ( ) . unwrap ( ) ;
261
267
262
- let get_info_request_id = client_node
263
- . liquidity_manager
264
- . lsps2_client_handler ( )
265
- . unwrap ( )
266
- . request_opening_params ( service_node_id, None ) ;
268
+ let get_info_request_id = client_handler. request_opening_params ( service_node_id, None ) ;
267
269
let get_info_request = get_lsps_message ! ( client_node, service_node_id) ;
268
270
service_node. liquidity_manager . handle_custom_message ( get_info_request, client_node_id) . unwrap ( ) ;
269
271
@@ -301,10 +303,7 @@ fn channel_open_failed() {
301
303
} ;
302
304
303
305
let payment_size_msat = Some ( 1_000_000 ) ;
304
- let buy_request_id = client_node
305
- . liquidity_manager
306
- . lsps2_client_handler ( )
307
- . unwrap ( )
306
+ let buy_request_id = client_handler
308
307
. select_opening_params ( service_node_id, payment_size_msat, opening_fee_params. clone ( ) )
309
308
. unwrap ( ) ;
310
309
let buy_request = get_lsps_message ! ( client_node, service_node_id) ;
@@ -410,13 +409,10 @@ fn channel_open_abandoned() {
410
409
let ( service_node_id, client_node_id, service_node, client_node, _) = setup_test_lsps2 ( ) ;
411
410
412
411
let service_handler = service_node. liquidity_manager . lsps2_service_handler ( ) . unwrap ( ) ;
412
+ let client_handler = client_node. liquidity_manager . lsps2_client_handler ( ) . unwrap ( ) ;
413
413
414
414
// Set up a JIT channel
415
- let get_info_request_id = client_node
416
- . liquidity_manager
417
- . lsps2_client_handler ( )
418
- . unwrap ( )
419
- . request_opening_params ( service_node_id, None ) ;
415
+ let get_info_request_id = client_handler. request_opening_params ( service_node_id, None ) ;
420
416
let get_info_request = get_lsps_message ! ( client_node, service_node_id) ;
421
417
service_node. liquidity_manager . handle_custom_message ( get_info_request, client_node_id) . unwrap ( ) ;
422
418
let _get_info_event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
@@ -453,10 +449,7 @@ fn channel_open_abandoned() {
453
449
} ;
454
450
455
451
let payment_size_msat = Some ( 1_000_000 ) ;
456
- let buy_request_id = client_node
457
- . liquidity_manager
458
- . lsps2_client_handler ( )
459
- . unwrap ( )
452
+ let buy_request_id = client_handler
460
453
. select_opening_params ( service_node_id, payment_size_msat, opening_fee_params. clone ( ) )
461
454
. unwrap ( ) ;
462
455
let buy_request = get_lsps_message ! ( client_node, service_node_id) ;
@@ -504,3 +497,248 @@ fn channel_open_abandoned_nonexistent_channel() {
504
497
other => panic ! ( "Unexpected error type: {:?}" , other) ,
505
498
}
506
499
}
500
+
501
+ #[ test]
502
+ fn max_pending_requests_per_peer_rejected ( ) {
503
+ let ( service_node_id, client_node_id, service_node, client_node, _) = setup_test_lsps2 ( ) ;
504
+
505
+ let client_handler = client_node. liquidity_manager . lsps2_client_handler ( ) . unwrap ( ) ;
506
+
507
+ for _ in 0 ..MAX_PENDING_REQUESTS_PER_PEER {
508
+ let _ = client_handler. request_opening_params ( service_node_id, None ) ;
509
+ let req_msg = get_lsps_message ! ( client_node, service_node_id) ;
510
+ let result = service_node. liquidity_manager . handle_custom_message ( req_msg, client_node_id) ;
511
+ assert ! ( result. is_ok( ) ) ;
512
+ let event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
513
+ match event {
514
+ LiquidityEvent :: LSPS2Service ( LSPS2ServiceEvent :: GetInfo { .. } ) => { } ,
515
+ _ => panic ! ( "Unexpected event" ) ,
516
+ }
517
+ }
518
+
519
+ // Test per-peer limit: the next request should be rejected
520
+ let rejected_req_id = client_handler. request_opening_params ( service_node_id, None ) ;
521
+ let rejected_req_msg = get_lsps_message ! ( client_node, service_node_id) ;
522
+
523
+ let result =
524
+ service_node. liquidity_manager . handle_custom_message ( rejected_req_msg, client_node_id) ;
525
+ assert ! ( result. is_err( ) , "We should have hit the per-peer limit" ) ;
526
+
527
+ let get_info_error_response = get_lsps_message ! ( service_node, client_node_id) ;
528
+ let result = client_node
529
+ . liquidity_manager
530
+ . handle_custom_message ( get_info_error_response, service_node_id) ;
531
+ assert ! ( result. is_err( ) ) ;
532
+
533
+ let event = client_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
534
+ match event {
535
+ LiquidityEvent :: LSPS2Client ( LSPS2ClientEvent :: GetInfoFailed {
536
+ request_id,
537
+ counterparty_node_id,
538
+ error,
539
+ } ) => {
540
+ assert_eq ! ( request_id, rejected_req_id) ;
541
+ assert_eq ! ( counterparty_node_id, service_node_id) ;
542
+ assert_eq ! ( error. code, 1 ) ; // LSPS0_CLIENT_REJECTED_ERROR_CODE
543
+ } ,
544
+ _ => panic ! ( "Expected LSPS2ClientEvent::GetInfoFailed event" ) ,
545
+ }
546
+ }
547
+
548
+ #[ test]
549
+ fn max_total_requests_buy_rejected ( ) {
550
+ let ( service_node_id, _, service_node, client_node, _) = setup_test_lsps2 ( ) ;
551
+
552
+ let client_handler = client_node. liquidity_manager . lsps2_client_handler ( ) . unwrap ( ) ;
553
+ let service_handler = service_node. liquidity_manager . lsps2_service_handler ( ) . unwrap ( ) ;
554
+ let secp = Secp256k1 :: new ( ) ;
555
+
556
+ let special_sk_bytes = [ 99u8 ; 32 ] ;
557
+ let special_sk = SecretKey :: from_slice ( & special_sk_bytes) . unwrap ( ) ;
558
+ let special_node_id = PublicKey :: from_secret_key ( & secp, & special_sk) ;
559
+
560
+ let _ = client_handler. request_opening_params ( service_node_id, None ) ;
561
+ let get_info_request = get_lsps_message ! ( client_node, service_node_id) ;
562
+ service_node
563
+ . liquidity_manager
564
+ . handle_custom_message ( get_info_request, special_node_id)
565
+ . unwrap ( ) ;
566
+
567
+ let get_info_event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
568
+ match get_info_event {
569
+ LiquidityEvent :: LSPS2Service ( LSPS2ServiceEvent :: GetInfo { request_id, .. } ) => {
570
+ let raw_opening_params = LSPS2RawOpeningFeeParams {
571
+ min_fee_msat : 100 ,
572
+ proportional : 21 ,
573
+ valid_until : LSPSDateTime :: from_str ( "2035-05-20T08:30:45Z" ) . unwrap ( ) ,
574
+ min_lifetime : 144 ,
575
+ max_client_to_self_delay : 128 ,
576
+ min_payment_size_msat : 1 ,
577
+ max_payment_size_msat : 100_000_000 ,
578
+ } ;
579
+
580
+ service_handler
581
+ . opening_fee_params_generated (
582
+ & special_node_id,
583
+ request_id,
584
+ vec ! [ raw_opening_params] ,
585
+ )
586
+ . unwrap ( ) ;
587
+ } ,
588
+ _ => panic ! ( "Unexpected event" ) ,
589
+ }
590
+
591
+ let get_info_response = get_lsps_message ! ( service_node, special_node_id) ;
592
+ client_node
593
+ . liquidity_manager
594
+ . handle_custom_message ( get_info_response, service_node_id)
595
+ . unwrap ( ) ;
596
+
597
+ let opening_params_event = client_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
598
+ let opening_fee_params = match opening_params_event {
599
+ LiquidityEvent :: LSPS2Client ( LSPS2ClientEvent :: OpeningParametersReady {
600
+ opening_fee_params_menu,
601
+ ..
602
+ } ) => opening_fee_params_menu. first ( ) . unwrap ( ) . clone ( ) ,
603
+ _ => panic ! ( "Unexpected event" ) ,
604
+ } ;
605
+
606
+ // Now fill up the global limit with additional GetInfo requests from other peers
607
+ let mut filled = 0 ;
608
+ let mut peer_idx = 0 ;
609
+
610
+ while filled < MAX_TOTAL_PENDING_REQUESTS {
611
+ let sk_bytes = [ peer_idx as u8 + 1 ; 32 ] ;
612
+ let sk = SecretKey :: from_slice ( & sk_bytes) . unwrap ( ) ;
613
+ let peer_node_id = PublicKey :: from_secret_key ( & secp, & sk) ;
614
+
615
+ // Skip if this is our special node
616
+ if peer_node_id == special_node_id {
617
+ peer_idx += 1 ;
618
+ continue ;
619
+ }
620
+
621
+ for _ in 0 ..MAX_PENDING_REQUESTS_PER_PEER {
622
+ if filled >= MAX_TOTAL_PENDING_REQUESTS {
623
+ break ;
624
+ }
625
+
626
+ let _ = client_handler. request_opening_params ( service_node_id, None ) ;
627
+ let req_msg = get_lsps_message ! ( client_node, service_node_id) ;
628
+ let result =
629
+ service_node. liquidity_manager . handle_custom_message ( req_msg, peer_node_id) ;
630
+ assert ! ( result. is_ok( ) ) ;
631
+
632
+ let event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
633
+ match event {
634
+ LiquidityEvent :: LSPS2Service ( LSPS2ServiceEvent :: GetInfo { .. } ) => { } ,
635
+ _ => panic ! ( "Unexpected event" ) ,
636
+ }
637
+
638
+ filled += 1 ;
639
+ }
640
+ peer_idx += 1 ;
641
+ }
642
+
643
+ // Now try to send a Buy request with our special node, which should be rejected
644
+ let payment_size_msat = Some ( 1_000_000 ) ;
645
+ let buy_request_id = client_handler
646
+ . select_opening_params ( service_node_id, payment_size_msat, opening_fee_params)
647
+ . unwrap ( ) ;
648
+ let buy_request = get_lsps_message ! ( client_node, service_node_id) ;
649
+
650
+ let result = service_node. liquidity_manager . handle_custom_message ( buy_request, special_node_id) ;
651
+ assert ! ( result. is_err( ) , "The Buy request should have been rejected" ) ;
652
+
653
+ let buy_error_response = get_lsps_message ! ( service_node, special_node_id) ;
654
+ let result =
655
+ client_node. liquidity_manager . handle_custom_message ( buy_error_response, service_node_id) ;
656
+ assert ! ( result. is_err( ) ) ;
657
+
658
+ let event = client_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
659
+ match event {
660
+ LiquidityEvent :: LSPS2Client ( LSPS2ClientEvent :: BuyRequestFailed {
661
+ request_id,
662
+ counterparty_node_id,
663
+ error,
664
+ } ) => {
665
+ assert_eq ! ( request_id, buy_request_id) ;
666
+ assert_eq ! ( counterparty_node_id, service_node_id) ;
667
+ assert_eq ! ( error. code, 1 ) ; // LSPS0_CLIENT_REJECTED_ERROR_CODE
668
+ } ,
669
+ _ => panic ! ( "Expected LSPS2ClientEvent::BuyRequestFailed event" ) ,
670
+ }
671
+ }
672
+
673
+ #[ test]
674
+ fn invalid_token_flow ( ) {
675
+ let ( service_node_id, client_node_id, service_node, client_node, _promise_secret) =
676
+ setup_test_lsps2 ( ) ;
677
+
678
+ let client_handler = client_node. liquidity_manager . lsps2_client_handler ( ) . unwrap ( ) ;
679
+ let service_handler = service_node. liquidity_manager . lsps2_service_handler ( ) . unwrap ( ) ;
680
+
681
+ let token = Some ( "invalid_token" . to_string ( ) ) ;
682
+ let get_info_request_id = client_handler. request_opening_params ( service_node_id, token) ;
683
+ let get_info_request = get_lsps_message ! ( client_node, service_node_id) ;
684
+
685
+ service_node. liquidity_manager . handle_custom_message ( get_info_request, client_node_id) . unwrap ( ) ;
686
+
687
+ let get_info_event = service_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
688
+ match get_info_event {
689
+ LiquidityEvent :: LSPS2Service ( LSPS2ServiceEvent :: GetInfo {
690
+ request_id,
691
+ counterparty_node_id,
692
+ token,
693
+ } ) => {
694
+ assert_eq ! ( request_id, get_info_request_id) ;
695
+ assert_eq ! ( counterparty_node_id, client_node_id) ;
696
+ assert_eq ! ( token, Some ( "invalid_token" . to_string( ) ) ) ;
697
+
698
+ // Service rejects the token as invalid
699
+ service_handler. invalid_token_provided ( & client_node_id, request_id. clone ( ) ) . unwrap ( ) ;
700
+
701
+ // Attempt to respond to the same request again which should fail
702
+ // because the request has been removed from pending_requests
703
+ let raw_opening_params = LSPS2RawOpeningFeeParams {
704
+ min_fee_msat : 100 ,
705
+ proportional : 21 ,
706
+ valid_until : LSPSDateTime :: from_str ( "2035-05-20T08:30:45Z" ) . unwrap ( ) ,
707
+ min_lifetime : 144 ,
708
+ max_client_to_self_delay : 128 ,
709
+ min_payment_size_msat : 1 ,
710
+ max_payment_size_msat : 100_000_000 ,
711
+ } ;
712
+
713
+ let result = service_handler. opening_fee_params_generated (
714
+ & client_node_id,
715
+ request_id. clone ( ) ,
716
+ vec ! [ raw_opening_params] ,
717
+ ) ;
718
+
719
+ assert ! ( result. is_err( ) , "Request should have been removed from pending_requests" ) ;
720
+ } ,
721
+ _ => panic ! ( "Unexpected event" ) ,
722
+ }
723
+
724
+ let get_info_error_response = get_lsps_message ! ( service_node, client_node_id) ;
725
+
726
+ client_node
727
+ . liquidity_manager
728
+ . handle_custom_message ( get_info_error_response, service_node_id)
729
+ . unwrap_err ( ) ;
730
+
731
+ let error_event = client_node. liquidity_manager . next_event ( ) . unwrap ( ) ;
732
+ match error_event {
733
+ LiquidityEvent :: LSPS2Client ( LSPS2ClientEvent :: GetInfoFailed {
734
+ request_id,
735
+ counterparty_node_id,
736
+ error,
737
+ } ) => {
738
+ assert_eq ! ( request_id, get_info_request_id) ;
739
+ assert_eq ! ( counterparty_node_id, service_node_id) ;
740
+ assert_eq ! ( error. code, 200 ) ; // LSPS2_GET_INFO_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE
741
+ } ,
742
+ _ => panic ! ( "Expected LSPS2ClientEvent::GetInfoFailed event" ) ,
743
+ }
744
+ }
0 commit comments