@@ -669,8 +669,8 @@ impl ChannelManager {
669669 Ok ( res)
670670 }
671671
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 > {
674674 let mut cur_value_msat = 0u64 ;
675675 let mut cur_cltv = starting_htlc_offset;
676676 let mut last_short_channel_id = 0 ;
@@ -685,7 +685,7 @@ impl ChannelManager {
685685 let value_msat = if cur_value_msat == 0 { hop. fee_msat } else { cur_value_msat } ;
686686 let cltv = if cur_cltv == starting_htlc_offset { hop. cltv_expiry_delta + starting_htlc_offset } else { cur_cltv } ;
687687 res[ idx] = msgs:: OnionHopData {
688- realm : 0 ,
688+ realm : realm ,
689689 data : msgs:: OnionRealm0HopData {
690690 short_channel_id : last_short_channel_id,
691691 amt_to_forward : value_msat,
@@ -706,6 +706,11 @@ impl ChannelManager {
706706 Ok ( ( res, cur_value_msat, cur_cltv) )
707707 }
708708
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+
709714 #[ inline]
710715 fn shift_arr_right ( arr : & mut [ u8 ; 20 * 65 ] ) {
711716 unsafe {
@@ -1083,11 +1088,15 @@ impl ChannelManager {
10831088 }
10841089 }
10851090
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+ } ;
10911100
10921101 let cur_height = self . latest_block_height . load ( Ordering :: Acquire ) as u32 + 1 ;
10931102
@@ -2552,12 +2561,12 @@ mod tests {
25522561 use chain:: chaininterface;
25532562 use chain:: transaction:: OutPoint ;
25542563 use chain:: chaininterface:: ChainListener ;
2555- use ln:: channelmanager:: { ChannelManager , OnionKeys } ;
2564+ use ln:: channelmanager:: { ChannelManager , OnionKeys , HTLCSource } ;
25562565 use ln:: channelmonitor:: { CLTV_CLAIM_BUFFER , HTLC_FAIL_TIMEOUT_BLOCKS } ;
25572566 use ln:: router:: { Route , RouteHop , Router } ;
25582567 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 } ;
25612570 use util:: events:: { Event , EventsProvider } ;
25622571 use util:: errors:: APIError ;
25632572 use util:: logger:: Logger ;
@@ -5389,4 +5398,248 @@ mod tests {
53895398 sign_msg ! ( unsigned_msg) ;
53905399 assert ! ( nodes[ 0 ] . router. handle_channel_announcement( & chan_announcement) . is_err( ) ) ;
53915400 }
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+ }
53925645}
0 commit comments