@@ -25,7 +25,8 @@ use ln::wire::Encode;
25
25
use util:: events:: { Event , MessageSendEvent , MessageSendEventsProvider } ;
26
26
use util:: ser:: { Writeable , Writer } ;
27
27
use util:: { byte_utils, test_utils} ;
28
- use util:: config:: UserConfig ;
28
+ use util:: config:: { UserConfig , HTLCRelayPolicyUpdate } ;
29
+ use util:: errors:: APIError ;
29
30
30
31
use bitcoin:: hash_types:: BlockHash ;
31
32
@@ -506,8 +507,6 @@ fn test_onion_failure() {
506
507
let preimage = send_along_route ( & nodes[ 0 ] , bogus_route, & [ & nodes[ 1 ] , & nodes[ 2 ] ] , amt_to_forward+1 ) . 0 ;
507
508
claim_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , preimage) ;
508
509
509
- //TODO: with new config API, we will be able to generate both valid and
510
- //invalid channel_update cases.
511
510
let short_channel_id = channels[ 0 ] . 0 . contents . short_channel_id ;
512
511
run_onion_failure_test ( "fee_insufficient" , 0 , & nodes, & route, & payment_hash, & payment_secret, |msg| {
513
512
msg. amount_msat -= 1 ;
@@ -594,6 +593,93 @@ fn test_onion_failure() {
594
593
} , true , Some ( 23 ) , None , None ) ;
595
594
}
596
595
596
+ #[ test]
597
+ fn test_onion_failure_stale_channel_update ( ) {
598
+ // Create a network of three nodes and two channels connecting them. We'll be updating the
599
+ // second channel with insane HTLC relay parameters, causing forwarding failures at the first
600
+ // hop.
601
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
602
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
603
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
604
+ let mut nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
605
+ create_announced_chan_between_nodes ( & nodes, 0 , 1 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
606
+ let channel_to_update = create_announced_chan_between_nodes (
607
+ & nodes, 1 , 2 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ,
608
+ ) ;
609
+
610
+ // A test payment should succeed as the HTLC relay paramters have not been changed yet.
611
+ const PAYMENT_AMT : u64 = 40000 ;
612
+ send_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] , & nodes[ 2 ] ) [ ..] , PAYMENT_AMT ) ;
613
+
614
+ // Closure to update and retrieve the latest ChannelUpdate.
615
+ let update_and_get_channel_update =
616
+ |updates : & [ HTLCRelayPolicyUpdate ] , expect_new_update : bool ,
617
+ prev_update : Option < & msgs:: ChannelUpdate > | -> Option < msgs:: ChannelUpdate > {
618
+ nodes[ 1 ] . node . update_htlc_relay_policy ( & [ channel_to_update. 2 ] , updates) . unwrap ( ) ;
619
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
620
+ assert_eq ! ( events. len( ) , expect_new_update as usize ) ;
621
+ if !expect_new_update {
622
+ return None ;
623
+ }
624
+ let new_update = match & events[ 0 ] {
625
+ MessageSendEvent :: BroadcastChannelUpdate { msg, .. } => msg. clone ( ) ,
626
+ _ => panic ! ( "expected BroadcastChannelUpdate event" ) ,
627
+ } ;
628
+ if prev_update. is_some ( ) {
629
+ assert ! ( new_update. contents. timestamp > prev_update. unwrap( ) . contents. timestamp)
630
+ }
631
+ Some ( new_update)
632
+ } ;
633
+
634
+ // We'll be attempting to route payments using the default ChannelUpdate for channels. This will
635
+ // lead to onion failures at the first hop once we update the HTLC relay parameters for the
636
+ // second hop.
637
+ let ( route, payment_hash, _, payment_secret) = get_route_and_payment_hash ! (
638
+ nodes[ 0 ] , nodes[ 2 ] , PAYMENT_AMT
639
+ ) ;
640
+ let expect_onion_failure = |name : & str , error_code : u16 , channel_update : & msgs:: ChannelUpdate | {
641
+ let short_channel_id = channel_to_update. 0 . contents . short_channel_id ;
642
+ let network_update = NetworkUpdate :: ChannelUpdateMessage { msg : channel_update. clone ( ) } ;
643
+ run_onion_failure_test (
644
+ name, 0 , & nodes, & route, & payment_hash, & payment_secret, |_| { } , || { } , true ,
645
+ Some ( error_code) , Some ( network_update) , Some ( short_channel_id) ,
646
+ ) ;
647
+ } ;
648
+
649
+ // Updates to cltv_expiry_delta below MIN_CLTV_EXPIRY_DELTA should fail with APIMisuseError.
650
+ let updates = & [ HTLCRelayPolicyUpdate :: CltvExpiryDelta ( Some ( MIN_CLTV_EXPIRY_DELTA - 1 ) ) ] ;
651
+ match nodes[ 1 ] . node . update_htlc_relay_policy ( & [ channel_to_update. 2 ] , updates) {
652
+ Err ( APIError :: APIMisuseError { .. } ) => { } ,
653
+ _ => panic ! ( "unexpected result applying invalid cltv_expiry_delta" ) ,
654
+ }
655
+
656
+ // Increase the base fee which should trigger a new ChannelUpdate.
657
+ let updates = & [ HTLCRelayPolicyUpdate :: ForwardingFeeBaseMsat ( Some ( u32:: MAX ) ) ] ;
658
+ let msg = update_and_get_channel_update ( updates, true , None ) . unwrap ( ) ;
659
+ expect_onion_failure ( "fee_insufficient" , UPDATE |12 , & msg) ;
660
+
661
+ // Redundant updates should not trigger a new ChannelUpdate.
662
+ assert ! ( update_and_get_channel_update( updates, false , None ) . is_none( ) ) ;
663
+
664
+ // Reset the base fee to the default and increase the proportional fee which should trigger a
665
+ // new ChannelUpdate.
666
+ let updates = & [
667
+ HTLCRelayPolicyUpdate :: ForwardingFeeBaseMsat ( None ) ,
668
+ HTLCRelayPolicyUpdate :: CltvExpiryDelta ( Some ( u16:: MAX ) ) ,
669
+ ] ;
670
+ let msg = update_and_get_channel_update ( updates, true , Some ( & msg) ) . unwrap ( ) ;
671
+ expect_onion_failure ( "incorrect_cltv_expiry" , UPDATE |13 , & msg) ;
672
+
673
+ // Reset the proportional fee and increase the CLTV expiry delta which should trigger a new
674
+ // ChannelUpdate.
675
+ let updates = & [
676
+ HTLCRelayPolicyUpdate :: CltvExpiryDelta ( None ) ,
677
+ HTLCRelayPolicyUpdate :: ForwardingFeeProportionalMillionths ( Some ( u32:: MAX ) ) ,
678
+ ] ;
679
+ let msg = update_and_get_channel_update ( updates, true , Some ( & msg) ) . unwrap ( ) ;
680
+ expect_onion_failure ( "fee_insufficient" , UPDATE |12 , & msg) ;
681
+ }
682
+
597
683
#[ test]
598
684
fn test_default_to_onion_payload_tlv_format ( ) {
599
685
// Tests that we default to creating tlv format onion payloads when no `NodeAnnouncementInfo`
0 commit comments