@@ -669,8 +669,8 @@ impl ChannelManager {
669
669
Ok ( res)
670
670
}
671
671
672
- /// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
673
- fn build_onion_payloads ( route : & Route , starting_htlc_offset : u32 ) -> Result < ( Vec < msgs:: OnionHopData > , u64 , u32 ) , APIError > {
672
+ // Only separated out for testing, we always use realm 0
673
+ fn build_onion_payloads_with_realm ( route : & Route , starting_htlc_offset : u32 , realm : u8 ) -> Result < ( Vec < msgs:: OnionHopData > , u64 , u32 ) , APIError > {
674
674
let mut cur_value_msat = 0u64 ;
675
675
let mut cur_cltv = starting_htlc_offset;
676
676
let mut last_short_channel_id = 0 ;
@@ -685,7 +685,7 @@ impl ChannelManager {
685
685
let value_msat = if cur_value_msat == 0 { hop. fee_msat } else { cur_value_msat } ;
686
686
let cltv = if cur_cltv == starting_htlc_offset { hop. cltv_expiry_delta + starting_htlc_offset } else { cur_cltv } ;
687
687
res[ idx] = msgs:: OnionHopData {
688
- realm : 0 ,
688
+ realm : realm ,
689
689
data : msgs:: OnionRealm0HopData {
690
690
short_channel_id : last_short_channel_id,
691
691
amt_to_forward : value_msat,
@@ -706,6 +706,11 @@ impl ChannelManager {
706
706
Ok ( ( res, cur_value_msat, cur_cltv) )
707
707
}
708
708
709
+ #[ inline]
710
+ fn build_onion_payloads ( route : & Route , starting_htlc_offset : u32 ) -> Result < ( Vec < msgs:: OnionHopData > , u64 , u32 ) , APIError > {
711
+ ChannelManager :: build_onion_payloads_with_realm ( route, starting_htlc_offset, 0 )
712
+ }
713
+
709
714
#[ inline]
710
715
fn shift_arr_right ( arr : & mut [ u8 ; 20 * 65 ] ) {
711
716
unsafe {
@@ -1083,11 +1088,15 @@ impl ChannelManager {
1083
1088
}
1084
1089
}
1085
1090
1086
- let session_priv = SecretKey :: from_slice ( & self . secp_ctx , & {
1087
- let mut session_key = [ 0 ; 32 ] ;
1088
- rng:: fill_bytes ( & mut session_key) ;
1089
- session_key
1090
- } ) . expect ( "RNG is bad!" ) ;
1091
+ let session_priv = if cfg ! ( test) {
1092
+ SecretKey :: from_slice ( & self . secp_ctx , & [ 3 ; 32 ] ) . unwrap ( )
1093
+ } else {
1094
+ SecretKey :: from_slice ( & self . secp_ctx , & {
1095
+ let mut session_key = [ 0 ; 32 ] ;
1096
+ rng:: fill_bytes ( & mut session_key) ;
1097
+ session_key
1098
+ } ) . expect ( "RNG is bad!" )
1099
+ } ;
1091
1100
1092
1101
let cur_height = self . latest_block_height . load ( Ordering :: Acquire ) as u32 + 1 ;
1093
1102
@@ -2552,12 +2561,12 @@ mod tests {
2552
2561
use chain:: chaininterface;
2553
2562
use chain:: transaction:: OutPoint ;
2554
2563
use chain:: chaininterface:: ChainListener ;
2555
- use ln:: channelmanager:: { ChannelManager , OnionKeys } ;
2564
+ use ln:: channelmanager:: { ChannelManager , OnionKeys , HTLCSource } ;
2556
2565
use ln:: channelmonitor:: { CLTV_CLAIM_BUFFER , HTLC_FAIL_TIMEOUT_BLOCKS } ;
2557
2566
use ln:: router:: { Route , RouteHop , Router } ;
2558
2567
use ln:: msgs;
2559
- use ln:: msgs:: { ChannelMessageHandler , RoutingMessageHandler } ;
2560
- use util:: test_utils;
2568
+ use ln:: msgs:: { ChannelMessageHandler , RoutingMessageHandler , HTLCFailChannelUpdate } ;
2569
+ use util:: { test_utils, rng } ;
2561
2570
use util:: events:: { Event , EventsProvider } ;
2562
2571
use util:: errors:: APIError ;
2563
2572
use util:: logger:: Logger ;
@@ -5389,4 +5398,248 @@ mod tests {
5389
5398
sign_msg ! ( unsigned_msg) ;
5390
5399
assert ! ( nodes[ 0 ] . router. handle_channel_announcement( & chan_announcement) . is_err( ) ) ;
5391
5400
}
5401
+
5402
+ fn run_onion_failure_test < F1 , F2 > ( _name : & str , test_case : u8 , nodes : & Vec < Node > , channels : & [ ( msgs:: ChannelUpdate , msgs:: ChannelUpdate , [ u8 ; 32 ] , Transaction ) ] , route : & Route , payment_hash : & [ u8 ; 32 ] , mut callback1 : F1 , mut callback2 : F2 , expected_retryable : bool , expected_error_code : Option < u16 > , expected_channel_update : Option < HTLCFailChannelUpdate > )
5403
+ where F1 : for < ' a > FnMut ( & ' a mut msgs:: UpdateAddHTLC ) ,
5404
+ F2 : for < ' a > FnMut ( & ' a mut msgs:: UpdateAddHTLC ) ,
5405
+ {
5406
+ use ln:: msgs:: HTLCFailChannelUpdate ;
5407
+
5408
+ // reset block height
5409
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
5410
+ for ix in 0 ..nodes. len ( ) {
5411
+ nodes[ ix] . chain_monitor . block_connected_checked ( & header, 1 , & Vec :: new ( ) [ ..] , & [ 0 ; 0 ] ) ;
5412
+ }
5413
+
5414
+ macro_rules! expect_update_htlc_event {
5415
+ ( $node: expr) => { {
5416
+ let events = $node. node. get_and_clear_pending_events( ) ;
5417
+ assert_eq!( events. len( ) , 1 ) ;
5418
+ match events[ 0 ] {
5419
+ Event :: UpdateHTLCs { node_id: _, ref updates } => { } ,
5420
+ _ => panic!( "Unexpected event" ) ,
5421
+ } ;
5422
+ $node. node. channel_state. lock( ) . unwrap( ) . next_forward = Instant :: now( ) ;
5423
+ $node. node. process_pending_htlc_forwards( ) ;
5424
+ } }
5425
+ }
5426
+
5427
+ macro_rules! expect_pending_htlcs_forwardable {
5428
+ ( $node: expr) => { {
5429
+ let events = $node. node. get_and_clear_pending_events( ) ;
5430
+ assert_eq!( events. len( ) , 1 ) ;
5431
+ match events[ 0 ] {
5432
+ Event :: PendingHTLCsForwardable { .. } => { } ,
5433
+ _ => panic!( "Unexpected event" ) ,
5434
+ } ;
5435
+ $node. node. channel_state. lock( ) . unwrap( ) . next_forward = Instant :: now( ) ;
5436
+ $node. node. process_pending_htlc_forwards( ) ;
5437
+ } }
5438
+ } ;
5439
+
5440
+ macro_rules! expect_pending_htlcs_forwardable {
5441
+ ( $node: expr) => { {
5442
+ let events = $node. node. get_and_clear_pending_events( ) ;
5443
+ assert_eq!( events. len( ) , 1 ) ;
5444
+ match events[ 0 ] {
5445
+ Event :: PendingHTLCsForwardable { .. } => { } ,
5446
+ _ => panic!( "Unexpected event" ) ,
5447
+ } ;
5448
+ $node. node. channel_state. lock( ) . unwrap( ) . next_forward = Instant :: now( ) ;
5449
+ $node. node. process_pending_htlc_forwards( ) ;
5450
+ } }
5451
+ } ;
5452
+
5453
+ macro_rules! expect_forward_event {
5454
+ ( $node: expr) => { {
5455
+ let mut events = $node. node. get_and_clear_pending_events( ) ;
5456
+ assert_eq!( events. len( ) , 1 ) ;
5457
+ check_added_monitors!( $node, 1 ) ;
5458
+ SendEvent :: from_event( events. remove( 0 ) )
5459
+ } }
5460
+ } ;
5461
+
5462
+ macro_rules! expect_forward_event {
5463
+ ( $node: expr) => { {
5464
+ let mut events = $node. node. get_and_clear_pending_events( ) ;
5465
+ assert_eq!( events. len( ) , 1 ) ;
5466
+ check_added_monitors!( $node, 1 ) ;
5467
+ SendEvent :: from_event( events. remove( 0 ) )
5468
+ } }
5469
+ } ;
5470
+
5471
+ macro_rules! expect_fail_backward_event {
5472
+ ( $node: expr) => { {
5473
+ let events = $node. node. get_and_clear_pending_events( ) ;
5474
+ assert_eq!( events. len( ) , 1 ) ;
5475
+ match events[ 0 ] {
5476
+ Event :: UpdateHTLCs { node_id: _, updates: msgs:: CommitmentUpdate { update_add_htlcs: _, update_fulfill_htlcs: _, ref update_fail_htlcs, update_fail_malformed_htlcs: _, update_fee: _, ref commitment_signed } } => {
5477
+ assert_eq!( update_fail_htlcs. len( ) , 1 ) ;
5478
+ ( update_fail_htlcs[ 0 ] . clone( ) , commitment_signed. clone( ) )
5479
+ } ,
5480
+ _ => panic!( "Unexpected event type!" ) ,
5481
+ }
5482
+ } }
5483
+ } ;
5484
+
5485
+ nodes[ 0 ] . node . send_payment ( route. clone ( ) , payment_hash. clone ( ) ) . unwrap ( ) ;
5486
+ let payment_event = expect_forward_event ! ( nodes[ 0 ] ) ;
5487
+ let mut update_add_1 = payment_event. msgs [ 0 ] . clone ( ) ;
5488
+
5489
+ callback1 ( & mut update_add_1) ;
5490
+
5491
+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & update_add_1) . unwrap ( ) ;
5492
+
5493
+ // 0 => 1
5494
+ let ( as_revoke_and_ack, as_commitment_signed) = nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. commitment_msg ) . unwrap ( ) ;
5495
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
5496
+ assert ! ( nodes[ 0 ] . node. handle_revoke_and_ack( & nodes[ 1 ] . node. get_our_node_id( ) , & as_revoke_and_ack) . unwrap( ) . is_none( ) ) ;
5497
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
5498
+ let ( bs_revoke_and_ack, bs_none) = nodes[ 0 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & as_commitment_signed. unwrap ( ) ) . unwrap ( ) ;
5499
+ assert ! ( bs_none. is_none( ) ) ;
5500
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
5501
+ let commitment_update = nodes[ 1 ] . node . handle_revoke_and_ack ( & nodes[ 0 ] . node . get_our_node_id ( ) , & bs_revoke_and_ack) . unwrap ( ) ;
5502
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
5503
+
5504
+ let ( update_fail_htlc, commitment_signed) = match test_case {
5505
+ 0 => { // intermediat node failure
5506
+ assert ! ( commitment_update. is_some( ) ) ;
5507
+ let commitment_update = commitment_update. unwrap ( ) ;
5508
+ assert ! ( commitment_update. update_fail_htlcs. len( ) == 1 ) ;
5509
+ ( commitment_update. update_fail_htlcs [ 0 ] . clone ( ) , commitment_update. commitment_signed )
5510
+ } ,
5511
+ 1 => { // final node failure
5512
+ assert ! ( commitment_update. is_none( ) ) ;
5513
+ expect_pending_htlcs_forwardable ! ( & nodes[ 1 ] ) ;
5514
+
5515
+ let ref payment_event = expect_forward_event ! ( nodes[ 1 ] ) ;
5516
+ let mut update_add_2 = payment_event. msgs [ 0 ] . clone ( ) ;
5517
+
5518
+ callback2 ( & mut update_add_2) ;
5519
+
5520
+ nodes[ 2 ] . node . handle_update_add_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & update_add_2) . unwrap ( ) ;
5521
+ let ( as_revoke_and_ack, as_commitment_signed) = nodes[ 2 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & payment_event. commitment_msg ) . unwrap ( ) ;
5522
+ check_added_monitors ! ( nodes[ 2 ] , 1 ) ;
5523
+ assert ! ( nodes[ 1 ] . node. handle_revoke_and_ack( & nodes[ 2 ] . node. get_our_node_id( ) , & as_revoke_and_ack) . unwrap( ) . is_none( ) ) ;
5524
+
5525
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
5526
+ let ( bs_revoke_and_ack, bs_none) = nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 2 ] . node . get_our_node_id ( ) , & as_commitment_signed. unwrap ( ) ) . unwrap ( ) ;
5527
+ assert ! ( bs_none. is_none( ) ) ;
5528
+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
5529
+ let commitment_update = nodes[ 2 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_revoke_and_ack) . unwrap ( ) . unwrap ( ) ;
5530
+ check_added_monitors ! ( nodes[ 2 ] , 1 ) ;
5531
+
5532
+ assert ! ( commitment_update. update_fail_htlcs. len( ) == 1 ) ;
5533
+ nodes[ 1 ] . node . handle_update_fail_htlc ( & nodes[ 2 ] . node . get_our_node_id ( ) , & commitment_update. update_fail_htlcs [ 0 ] ) . unwrap ( ) ;
5534
+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 2 ] , commitment_update. commitment_signed, true ) ;
5535
+
5536
+ let ( update_fail_htlc_msg, commitment_signed) = expect_fail_backward_event ! ( nodes[ 1 ] ) ;
5537
+ ( update_fail_htlc_msg, commitment_signed)
5538
+ } ,
5539
+ _ => unreachable ! ( ) ,
5540
+ } ;
5541
+
5542
+ // origin node fail handling
5543
+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & update_fail_htlc) . unwrap ( ) ;
5544
+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , commitment_signed, false ) ;
5545
+
5546
+ let events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
5547
+ //TODO assert_eq!(events.len(), 2);
5548
+ for evt in events. iter ( ) {
5549
+ match evt {
5550
+ & Event :: PaymentFailed { payment_hash : _, ref rejected_by_dest} => {
5551
+ assert_eq ! ( * rejected_by_dest, !expected_retryable) ;
5552
+ } ,
5553
+ & Event :: RouteUpdate { ref update } => {
5554
+ /* TODO check expected channel update */
5555
+ /*
5556
+ expected_channel_update.unwrap()
5557
+ assert!(expected_channel_update.is_some());
5558
+ if let Some(expected_update) = expected_channel_update {
5559
+ assert!(fail_channel_update.is_some());
5560
+ match fail_channel_update.unwrap() {
5561
+ expected_update => {},
5562
+ _ => panic!("Unexpected channel update"),
5563
+ }
5564
+ }
5565
+ */
5566
+ } ,
5567
+ _ => panic ! ( "Unexpected event" ) ,
5568
+ } ;
5569
+ }
5570
+ }
5571
+
5572
+ #[ test]
5573
+ fn test_onion_failure ( ) {
5574
+ use ln:: msgs:: ChannelUpdate ;
5575
+ use ln:: channelmanager:: CLTV_FAR_FAR_AWAY ;
5576
+ use bitcoin:: blockdata:: transaction:: Transaction ;
5577
+
5578
+ const BADONION : u16 = 0x8000 ;
5579
+ const PERM : u16 = 0x4000 ;
5580
+ const NODE : u16 = 0x1000 ;
5581
+ const UPDATE : u16 = 0x1000 ;
5582
+
5583
+ let mut nodes = create_network ( 3 ) ;
5584
+ let channels = [ create_announced_chan_between_nodes ( & nodes, 0 , 1 ) , create_announced_chan_between_nodes ( & nodes, 1 , 2 ) ] ;
5585
+ let ( _, payment_hash) = get_payment_preimage_hash ! ( nodes[ 0 ] ) ;
5586
+ let route = nodes[ 0 ] . router . get_route ( & nodes[ 2 ] . node . get_our_node_id ( ) , None , & Vec :: new ( ) , 40000 , TEST_FINAL_CLTV ) . unwrap ( ) ;
5587
+ //
5588
+ run_onion_failure_test ( "invalid_realm" , 0 , & nodes, & channels, & route, & payment_hash, |msg| {
5589
+ let session_priv = SecretKey :: from_slice ( & :: secp256k1:: Secp256k1 :: without_caps ( ) , & [ 3 ; 32 ] ) . unwrap ( ) ;
5590
+ let cur_height = nodes[ 0 ] . node . latest_block_height . load ( Ordering :: Acquire ) as u32 + 1 ;
5591
+ let onion_keys = ChannelManager :: construct_onion_keys ( & Secp256k1 :: new ( ) , & route, & session_priv) . unwrap ( ) ;
5592
+ let ( onion_payloads, _htlc_msat, _htlc_cltv) = ChannelManager :: build_onion_payloads_with_realm ( & route, cur_height, 100 ) . unwrap ( ) ;
5593
+ let onion_packet = ChannelManager :: construct_onion_packet ( onion_payloads, onion_keys, & payment_hash) ;
5594
+ msg. onion_routing_packet = onion_packet;
5595
+ } , |_msg| { } , true , Some ( PERM |1 ) , None ) ;
5596
+
5597
+ //TODO temporary_node_failure(NODE|2)
5598
+ //TODO permanent_node_failure(PERM|NODE|2)
5599
+ //TODO required_node_feature_missing
5600
+ run_onion_failure_test ( "invalid_onion_version" , 0 , & nodes, & channels, & route, & payment_hash, |msg| { msg. onion_routing_packet . version = 1 ; } , |_msg| { } , true , Some ( BADONION |PERM |4 ) , None ) ;
5601
+ run_onion_failure_test ( "invalid_onion_hmac" , 0 , & nodes, & channels, & route, & payment_hash, |msg| { msg. onion_routing_packet . hmac = [ 3 ; 32 ] ; } , |_msg| { } , true , Some ( BADONION |PERM |5 ) , None ) ;
5602
+ //TODO invalid_onion_key
5603
+ //TODO temporary_channel_failure(UPDATE|7)
5604
+ //TODO permanent_channel_failure(PERM|8)
5605
+ //TODO required_channel_feature_missing(PERM|9)
5606
+ //TODO unknown_next_peer(PERM|10)
5607
+ //TODO amount_below_minimum(UPDATE|11)
5608
+ //TODO fee_insufficient(UPDATE|12)
5609
+ run_onion_failure_test ( "incorrect_cltv_expiry" , 0 , & nodes, & channels, & route, & payment_hash, |msg| {
5610
+ // need to violate: cltv_expiry - cltv_expiry_delta >= outgoing_cltv_value
5611
+ msg. cltv_expiry -= 1 ;
5612
+ } , |_msg| { } , true , Some ( UPDATE |13 ) , None ) ;
5613
+ run_onion_failure_test ( "expiry_too_soon" , 0 , & nodes, & channels, & route, & payment_hash, |msg| {
5614
+ let height = msg. cltv_expiry - CLTV_CLAIM_BUFFER - HTLC_FAIL_TIMEOUT_BLOCKS + 1 ;
5615
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
5616
+ nodes[ 1 ] . chain_monitor . block_connected_checked ( & header, height, & Vec :: new ( ) [ ..] , & [ 0 ; 0 ] ) ;
5617
+ } , |_msg| { } , true , Some ( UPDATE |14 ) , None ) ;
5618
+ // TODO: unknown_payment_hash (PERM|15)
5619
+ // TODO: unknown_payment_amount (PERM|15)
5620
+ run_onion_failure_test ( "final_expiry_too_soon" , 1 , & nodes, & channels, & route, & payment_hash, |_msg| { } , |msg| {
5621
+ let height = msg. cltv_expiry - CLTV_CLAIM_BUFFER - HTLC_FAIL_TIMEOUT_BLOCKS + 1 ;
5622
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
5623
+ nodes[ 2 ] . chain_monitor . block_connected_checked ( & header, height, & Vec :: new ( ) [ ..] , & [ 0 ; 0 ] ) ;
5624
+ } , true , Some ( 17 ) , None ) ;
5625
+ run_onion_failure_test ( "final_incorrect_cltv_expiry" , 1 , & nodes, & channels, & route, & payment_hash, |_msg| { } , |msg| { msg. cltv_expiry += 1 ; } , true , Some ( 18 ) , None ) ;
5626
+ /* TODO this raise 'Invalid commitment tx signature from peer'
5627
+ run_onion_failure_test("final_incorrect_htlc_amount", 1, &nodes, &channels, &route, &payment_hash, |_msg| {}, |msg| {
5628
+ // violate amt_to_forward > msg.amount_msat
5629
+ msg.amount_msat -= 1;
5630
+ }, true, Some(19), None);
5631
+ */
5632
+ // TODO: channel_disabled (UPDATE|20)
5633
+ run_onion_failure_test ( "expiry_too_far" , 0 , & nodes, & channels, & route, & payment_hash, |msg| {
5634
+ let session_priv = SecretKey :: from_slice ( & :: secp256k1:: Secp256k1 :: without_caps ( ) , & [ 3 ; 32 ] ) . unwrap ( ) ;
5635
+ let mut route = route. clone ( ) ;
5636
+ let height = 1 ;
5637
+ route. hops [ 1 ] . cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route. hops [ 0 ] . cltv_expiry_delta + 1 ;
5638
+ let onion_keys = ChannelManager :: construct_onion_keys ( & Secp256k1 :: new ( ) , & route, & session_priv) . unwrap ( ) ;
5639
+ let ( onion_payloads, _htlc_msat, htlc_cltv) = ChannelManager :: build_onion_payloads ( & route, height) . unwrap ( ) ;
5640
+ let onion_packet = ChannelManager :: construct_onion_packet ( onion_payloads, onion_keys, & payment_hash) ;
5641
+ msg. cltv_expiry = htlc_cltv;
5642
+ msg. onion_routing_packet = onion_packet;
5643
+ } , |_msg| { } , true , Some ( 21 ) , None ) ;
5644
+ }
5392
5645
}
0 commit comments