@@ -1044,22 +1044,43 @@ where
10441044 let amt_to_forward = htlc_msat - route_hop. fee_msat ;
10451045 htlc_msat = amt_to_forward;
10461046
1047- let err_packet = match decrypt_onion_error_packet ( & mut encrypted_packet, shared_secret) {
1048- Ok ( p) => p,
1049- Err ( _) => return ,
1050- } ;
1047+ let decrypt_result = decrypt_onion_error_packet ( & mut encrypted_packet, shared_secret) ;
1048+
10511049 let um = gen_um_from_shared_secret ( shared_secret. as_ref ( ) ) ;
10521050 let mut hmac = HmacEngine :: < Sha256 > :: new ( & um) ;
1053- hmac. input ( & err_packet . encode ( ) [ 32 ..] ) ;
1051+ hmac. input ( & encrypted_packet [ 32 ..] ) ;
10541052
1055- if !fixed_time_eq ( & Hmac :: from_engine ( hmac) . to_byte_array ( ) , & err_packet . hmac ) {
1053+ if !fixed_time_eq ( & Hmac :: from_engine ( hmac) . to_byte_array ( ) , & encrypted_packet [ .. 32 ] ) {
10561054 return ;
10571055 }
1056+
1057+ let err_packet = match decrypt_result {
1058+ Ok ( p) => p,
1059+ Err ( _) => {
1060+ log_warn ! ( logger, "Unreadable failure from {}" , route_hop. pubkey) ;
1061+
1062+ let network_update = Some ( NetworkUpdate :: NodeFailure {
1063+ node_id : route_hop. pubkey ,
1064+ is_permanent : true ,
1065+ } ) ;
1066+ let short_channel_id = Some ( route_hop. short_channel_id ) ;
1067+ res = Some ( FailureLearnings {
1068+ network_update,
1069+ short_channel_id,
1070+ payment_failed_permanently : is_from_final_node,
1071+ failed_within_blinded_path : false ,
1072+ } ) ;
1073+ return ;
1074+ } ,
1075+ } ;
1076+
10581077 let error_code_slice = match err_packet. failuremsg . get ( 0 ..2 ) {
10591078 Some ( s) => s,
10601079 None => {
10611080 // Useless packet that we can't use but it passed HMAC, so it definitely came from the peer
10621081 // in question
1082+ log_warn ! ( logger, "Missing error code in failure from {}" , route_hop. pubkey) ;
1083+
10631084 let network_update = Some ( NetworkUpdate :: NodeFailure {
10641085 node_id : route_hop. pubkey ,
10651086 is_permanent : true ,
@@ -1219,6 +1240,12 @@ where
12191240 } else {
12201241 // only not set either packet unparseable or hmac does not match with any
12211242 // payment not retryable only when garbage is from the final node
1243+ log_warn ! (
1244+ logger,
1245+ "Non-attributable failure encountered on route {}" ,
1246+ path. hops. iter( ) . map( |h| h. pubkey. to_string( ) ) . collect:: <Vec <_>>( ) . join( "->" )
1247+ ) ;
1248+
12221249 DecodedOnionFailure {
12231250 network_update : None ,
12241251 short_channel_id : None ,
@@ -1768,7 +1795,7 @@ mod tests {
17681795
17691796 use crate :: io;
17701797 use crate :: ln:: channelmanager:: PaymentId ;
1771- use crate :: ln:: msgs;
1798+ use crate :: ln:: msgs:: { self , OnionErrorPacket } ;
17721799 use crate :: routing:: router:: { Path , PaymentParameters , Route , RouteHop } ;
17731800 use crate :: types:: features:: { ChannelFeatures , NodeFeatures } ;
17741801 use crate :: types:: payment:: PaymentHash ;
@@ -2104,6 +2131,81 @@ mod tests {
21042131 assert_eq ! ( decrypted_failure. onion_error_code, Some ( 0x2002 ) ) ;
21052132 }
21062133
2134+ #[ test]
2135+ fn test_non_attributable_failure_packet_onion ( ) {
2136+ let corrupt_failure_packet = vec ! [ 1u8 ; 292 ] ;
2137+
2138+ let logger: Arc < TestLogger > = Arc :: new ( TestLogger :: new ( ) ) ;
2139+ let ctx_full = Secp256k1 :: new ( ) ;
2140+ let path = build_test_path ( ) ;
2141+ let htlc_source = HTLCSource :: OutboundRoute {
2142+ path : path,
2143+ session_priv : get_test_session_key ( ) ,
2144+ first_hop_htlc_msat : 0 ,
2145+ payment_id : PaymentId ( [ 1 ; 32 ] )
2146+ , } ;
2147+
2148+ // For a corrupt failure message, the failing channel cannot be identified.
2149+ let decrypted_failure = process_onion_failure ( & ctx_full, & logger, & htlc_source, corrupt_failure_packet) ;
2150+ assert_eq ! ( decrypted_failure. short_channel_id, None ) ;
2151+ }
2152+
2153+ #[ test]
2154+ fn test_unreadable_failure_packet_onion ( ) {
2155+ // Create a failure packet with a valid hmac but unreadable failure message.
2156+ let onion_keys: Vec < OnionKeys > = build_test_onion_keys ( ) ;
2157+ let shared_secret = onion_keys[ 0 ] . shared_secret . as_ref ( ) ;
2158+ let um = gen_um_from_shared_secret ( & shared_secret) ;
2159+
2160+ // The failure message is a single 0 byte.
2161+ let mut packet = [ 0u8 ; 33 ] ;
2162+
2163+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & um) ;
2164+ hmac. input ( & packet[ 32 ..] ) ;
2165+ let hmac = Hmac :: from_engine ( hmac) . to_byte_array ( ) ;
2166+ packet[ ..32 ] . copy_from_slice ( & hmac) ;
2167+
2168+ let packet = encrypt_failure_packet ( shared_secret, & packet) ;
2169+
2170+ test_failure_attribution ( packet) ;
2171+ }
2172+
2173+ #[ test]
2174+ fn test_missing_error_code ( ) {
2175+ // Create a failure packet with a valid hmac and structure, but no error code.
2176+ let onion_keys: Vec < OnionKeys > = build_test_onion_keys ( ) ;
2177+ let shared_secret = onion_keys[ 0 ] . shared_secret . as_ref ( ) ;
2178+ let um = gen_um_from_shared_secret ( & shared_secret) ;
2179+
2180+ let failuremsg = vec ! [ 1 ] ;
2181+ let pad = Vec :: new ( ) ;
2182+ let mut packet = msgs:: DecodedOnionErrorPacket { hmac : [ 0 ; 32 ] , failuremsg, pad } ;
2183+
2184+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & um) ;
2185+ hmac. input ( & packet. encode ( ) [ 32 ..] ) ;
2186+ packet. hmac = Hmac :: from_engine ( hmac) . to_byte_array ( ) ;
2187+
2188+ let packet = encrypt_failure_packet ( shared_secret, & packet. encode ( ) [ ..] ) ;
2189+
2190+ test_failure_attribution ( packet) ;
2191+ }
2192+
2193+ fn test_failure_attribution ( packet : OnionErrorPacket ) {
2194+ let logger: Arc < TestLogger > = Arc :: new ( TestLogger :: new ( ) ) ;
2195+ let ctx_full = Secp256k1 :: new ( ) ;
2196+ let path = build_test_path ( ) ;
2197+ let htlc_source = HTLCSource :: OutboundRoute {
2198+ path : path,
2199+ session_priv : get_test_session_key ( ) ,
2200+ first_hop_htlc_msat : 0 ,
2201+ payment_id : PaymentId ( [ 1 ; 32 ] )
2202+ , } ;
2203+
2204+ // For the unreadable failure, it is still expected that the failing channel can be identified.
2205+ let decrypted_failure = process_onion_failure ( & ctx_full, & logger, & htlc_source, packet. data ) ;
2206+ assert_eq ! ( decrypted_failure. short_channel_id, Some ( 0 ) ) ;
2207+ }
2208+
21072209 struct RawOnionHopData {
21082210 data : Vec < u8 > ,
21092211 }
0 commit comments