@@ -1043,23 +1043,32 @@ where
1043
1043
htlc_msat = amt_to_forward;
1044
1044
1045
1045
decrypt_onion_error_packet ( & mut encrypted_packet, shared_secret) ;
1046
- let err_packet =
1047
- match msgs:: DecodedOnionErrorPacket :: read ( & mut Cursor :: new ( & encrypted_packet) ) {
1048
- Ok ( p) => p,
1049
- Err ( _) => return ,
1050
- } ;
1046
+
1051
1047
let um = gen_um_from_shared_secret ( shared_secret. as_ref ( ) ) ;
1052
1048
let mut hmac = HmacEngine :: < Sha256 > :: new ( & um) ;
1053
- hmac. input ( & err_packet . encode ( ) [ 32 ..] ) ;
1049
+ hmac. input ( & encrypted_packet [ 32 ..] ) ;
1054
1050
1055
- if !fixed_time_eq ( & Hmac :: from_engine ( hmac) . to_byte_array ( ) , & err_packet . hmac ) {
1051
+ if !fixed_time_eq ( & Hmac :: from_engine ( hmac) . to_byte_array ( ) , & encrypted_packet [ .. 32 ] ) {
1056
1052
return ;
1057
1053
}
1054
+
1055
+ let err_packet =
1056
+ match msgs:: DecodedOnionErrorPacket :: read ( & mut Cursor :: new ( & encrypted_packet) ) {
1057
+ Ok ( p) => p,
1058
+ Err ( _) => {
1059
+ log_warn ! ( logger, "Unreadable failure from {}" , route_hop. pubkey) ;
1060
+
1061
+ return ;
1062
+ } ,
1063
+ } ;
1064
+
1058
1065
let error_code_slice = match err_packet. failuremsg . get ( 0 ..2 ) {
1059
1066
Some ( s) => s,
1060
1067
None => {
1061
1068
// Useless packet that we can't use but it passed HMAC, so it definitely came from the peer
1062
1069
// in question
1070
+ log_warn ! ( logger, "Missing error code in failure from {}" , route_hop. pubkey) ;
1071
+
1063
1072
let network_update = Some ( NetworkUpdate :: NodeFailure {
1064
1073
node_id : route_hop. pubkey ,
1065
1074
is_permanent : true ,
@@ -1219,6 +1228,12 @@ where
1219
1228
} else {
1220
1229
// only not set either packet unparseable or hmac does not match with any
1221
1230
// payment not retryable only when garbage is from the final node
1231
+ log_warn ! (
1232
+ logger,
1233
+ "Non-attributable failure encountered on route {}" ,
1234
+ path. hops. iter( ) . map( |h| h. pubkey. to_string( ) ) . collect:: <Vec <_>>( ) . join( "->" )
1235
+ ) ;
1236
+
1222
1237
DecodedOnionFailure {
1223
1238
network_update : None ,
1224
1239
short_channel_id : None ,
@@ -2155,6 +2170,67 @@ mod tests {
2155
2170
assert_eq ! ( decrypted_failure. onion_error_code, Some ( 0x2002 ) ) ;
2156
2171
}
2157
2172
2173
+ #[ test]
2174
+ fn test_non_attributable_failure_packet_onion ( ) {
2175
+ // Create a failure packet with bogus data.
2176
+ let packet = vec ! [ 1u8 ; 292 ] ;
2177
+
2178
+ // In the current protocol, it is unfortunately not possible to identify the failure source.
2179
+ let logger = TestLogger :: new ( ) ;
2180
+ let decrypted_failure = test_failure_attribution ( & logger, & packet) ;
2181
+ assert_eq ! ( decrypted_failure. short_channel_id, None ) ;
2182
+
2183
+ logger. assert_log_contains (
2184
+ "lightning::ln::onion_utils" ,
2185
+ "Non-attributable failure encountered" ,
2186
+ 1 ,
2187
+ ) ;
2188
+ }
2189
+
2190
+ #[ test]
2191
+ fn test_missing_error_code ( ) {
2192
+ // Create a failure packet with a valid hmac and structure, but no error code.
2193
+ let onion_keys: Vec < OnionKeys > = build_test_onion_keys ( ) ;
2194
+ let shared_secret = onion_keys[ 0 ] . shared_secret . as_ref ( ) ;
2195
+ let um = gen_um_from_shared_secret ( & shared_secret) ;
2196
+
2197
+ let failuremsg = vec ! [ 1 ] ;
2198
+ let pad = Vec :: new ( ) ;
2199
+ let mut packet = msgs:: DecodedOnionErrorPacket { hmac : [ 0 ; 32 ] , failuremsg, pad } ;
2200
+
2201
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & um) ;
2202
+ hmac. input ( & packet. encode ( ) [ 32 ..] ) ;
2203
+ packet. hmac = Hmac :: from_engine ( hmac) . to_byte_array ( ) ;
2204
+
2205
+ let packet = encrypt_failure_packet ( shared_secret, & packet. encode ( ) [ ..] ) ;
2206
+
2207
+ let logger = TestLogger :: new ( ) ;
2208
+ let decrypted_failure = test_failure_attribution ( & logger, & packet. data ) ;
2209
+ assert_eq ! ( decrypted_failure. short_channel_id, Some ( 0 ) ) ;
2210
+
2211
+ logger. assert_log_contains (
2212
+ "lightning::ln::onion_utils" ,
2213
+ "Missing error code in failure" ,
2214
+ 1 ,
2215
+ ) ;
2216
+ }
2217
+
2218
+ fn test_failure_attribution ( logger : & TestLogger , packet : & [ u8 ] ) -> DecodedOnionFailure {
2219
+ let ctx_full = Secp256k1 :: new ( ) ;
2220
+ let path = build_test_path ( ) ;
2221
+ let htlc_source = HTLCSource :: OutboundRoute {
2222
+ path,
2223
+ session_priv : get_test_session_key ( ) ,
2224
+ first_hop_htlc_msat : 0 ,
2225
+ payment_id : PaymentId ( [ 1 ; 32 ] ) ,
2226
+ } ;
2227
+
2228
+ let decrypted_failure =
2229
+ process_onion_failure ( & ctx_full, & logger, & htlc_source, packet. into ( ) ) ;
2230
+
2231
+ decrypted_failure
2232
+ }
2233
+
2158
2234
struct RawOnionHopData {
2159
2235
data : Vec < u8 > ,
2160
2236
}
0 commit comments