@@ -11,7 +11,7 @@ use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
1111use ln:: channelmanager:: HTLCSource ;
1212use ln:: msgs;
1313use routing:: network_graph:: NetworkUpdate ;
14- use routing:: router:: RouteHop ;
14+ use routing:: router:: { FailingRouteHop , RouteHop } ;
1515use util:: chacha20:: ChaCha20 ;
1616use util:: errors:: { self , APIError } ;
1717use util:: ser:: { Readable , Writeable , LengthCalculatingWriter } ;
@@ -331,7 +331,7 @@ pub(super) fn build_first_hop_failure_packet(shared_secret: &[u8], failure_type:
331331/// OutboundRoute).
332332/// Returns update, a boolean indicating that the payment itself failed, and the error code.
333333#[ inline]
334- pub ( super ) fn process_onion_failure < T : secp256k1:: Signing , L : Deref > ( secp_ctx : & Secp256k1 < T > , logger : & L , htlc_source : & HTLCSource , mut packet_decrypted : Vec < u8 > ) -> ( Option < NetworkUpdate > , bool , Option < u16 > , Option < Vec < u8 > > ) where L :: Target : Logger {
334+ pub ( super ) fn process_onion_failure < T : secp256k1:: Signing , L : Deref > ( secp_ctx : & Secp256k1 < T > , logger : & L , htlc_source : & HTLCSource , mut packet_decrypted : Vec < u8 > ) -> ( Option < NetworkUpdate > , Option < FailingRouteHop > , bool , Option < u16 > , Option < Vec < u8 > > ) where L :: Target : Logger {
335335 if let & HTLCSource :: OutboundRoute { ref path, ref session_priv, ref first_hop_htlc_msat } = htlc_source {
336336 let mut res = None ;
337337 let mut htlc_msat = * first_hop_htlc_msat;
@@ -382,6 +382,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
382382 || error_code == 21 ; // Special case error 21 as the Route object is bogus, TODO: Maybe fail the node if the CLTV was reasonable?
383383
384384 let mut network_update = None ;
385+ let mut failing_route_hop = None ;
385386
386387 if error_code & NODE == NODE {
387388 network_update = Some ( NetworkUpdate :: NodeFailure { node_id : route_hop. pubkey , is_permanent : error_code & PERM == PERM } ) ;
@@ -394,6 +395,12 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
394395 is_permanent : true ,
395396 } )
396397 } ;
398+ failing_route_hop = if payment_failed { None } else {
399+ Some ( FailingRouteHop {
400+ path : path. clone ( ) ,
401+ index : if is_from_final_node { route_hop_idx } else { route_hop_idx + 1 } as u16 ,
402+ } )
403+ }
397404 }
398405 else if error_code & UPDATE == UPDATE {
399406 if let Some ( update_len_slice) = err_packet. failuremsg . get ( debug_field_size+2 ..debug_field_size+4 ) {
@@ -447,10 +454,17 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
447454 } ) ;
448455 }
449456
457+ if failing_route_hop. is_none ( ) {
458+ failing_route_hop = Some ( FailingRouteHop {
459+ path : path. clone ( ) ,
460+ index : route_hop_idx as u16 ,
461+ } ) ;
462+ }
463+
450464 // TODO: Here (and a few other places) we assume that BADONION errors
451465 // are always "sourced" from the node previous to the one which failed
452466 // to decode the onion.
453- res = Some ( ( network_update, !( error_code & PERM == PERM && is_from_final_node) ) ) ;
467+ res = Some ( ( network_update, failing_route_hop , !( error_code & PERM == PERM && is_from_final_node) ) ) ;
454468
455469 let ( description, title) = errors:: get_onion_error_description ( error_code) ;
456470 if debug_field_size > 0 && err_packet. failuremsg . len ( ) >= 4 + debug_field_size {
@@ -462,20 +476,25 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
462476 } else {
463477 // Useless packet that we can't use but it passed HMAC, so it
464478 // definitely came from the peer in question
465- res = Some ( ( Some ( NetworkUpdate :: NodeFailure {
479+ let network_update = Some ( NetworkUpdate :: NodeFailure {
466480 node_id : route_hop. pubkey ,
467481 is_permanent : true ,
468- } ) , !is_from_final_node) ) ;
482+ } ) ;
483+ let failing_route_hop = Some ( FailingRouteHop {
484+ path : path. clone ( ) ,
485+ index : route_hop_idx as u16 ,
486+ } ) ;
487+ res = Some ( ( network_update, failing_route_hop, !is_from_final_node) ) ;
469488 }
470489 }
471490 }
472491 } ) . expect ( "Route that we sent via spontaneously grew invalid keys in the middle of it?" ) ;
473- if let Some ( ( channel_update, payment_retryable) ) = res {
474- ( channel_update, payment_retryable, error_code_ret, error_packet_ret)
492+ if let Some ( ( channel_update, failing_route_hop , payment_retryable) ) = res {
493+ ( channel_update, failing_route_hop , payment_retryable, error_code_ret, error_packet_ret)
475494 } else {
476495 // only not set either packet unparseable or hmac does not match with any
477496 // payment not retryable only when garbage is from the final node
478- ( None , !is_from_final_node, None , None )
497+ ( None , None , !is_from_final_node, None , None )
479498 }
480499 } else { unreachable ! ( ) ; }
481500}
0 commit comments