@@ -1274,12 +1274,29 @@ where
1274
1274
}
1275
1275
1276
1276
1277
+ struct AttributableFailure {
1278
+ failure_index : usize ,
1279
+
1280
+ result : AttributableFailureResult ,
1281
+ }
1282
+
1283
+ struct AttributableFailureSuccess {
1284
+ message : Vec < u8 > ,
1285
+ hold_times : Vec < u32 > ,
1286
+ }
1287
+
1288
+ enum AttributableFailureResult {
1289
+ Success ( AttributableFailureSuccess ) ,
1290
+ InvalidPayload ,
1291
+ InvalidHmac
1292
+ }
1293
+
1277
1294
/// Process failure we got back from upstream on a payment we sent (implying htlc_source is an
1278
1295
/// OutboundRoute).
1279
1296
#[ inline]
1280
1297
pub ( super ) fn process_attributable_onion_failure < T : secp256k1:: Signing , L : Deref > (
1281
1298
secp_ctx : & Secp256k1 < T > , logger : & L , htlc_source : & HTLCSource , mut encrypted_packet : Vec < u8 > ,
1282
- ) -> Option < Vec < u8 > >
1299
+ ) -> AttributableFailure
1283
1300
where
1284
1301
L :: Target : Logger ,
1285
1302
{
@@ -1293,7 +1310,7 @@ where
1293
1310
} ;
1294
1311
1295
1312
// Learnings from the HTLC failure to inform future payment retries and scoring.
1296
- let mut res: Option < Vec < u8 > > = None ;
1313
+ let mut res: Option < AttributableFailure > = None ;
1297
1314
let mut is_from_final_node = false ;
1298
1315
1299
1316
// Handle packed channel/node updates for passing back for the route handler
@@ -1381,6 +1398,11 @@ where
1381
1398
let expected_hmac= & Hmac :: from_engine ( hmac) . to_byte_array ( ) [ ..HMAC_LEN ] ;
1382
1399
1383
1400
if !fixed_time_eq ( expected_hmac, actual_hmac) {
1401
+ res = Some ( AttributableFailure {
1402
+ failure_index : route_hop_idx,
1403
+ result : AttributableFailureResult :: InvalidHmac ,
1404
+ } ) ;
1405
+
1384
1406
log_debug ! ( logger, "Invalid HMAC in onion failure packet at pos {}" , route_hop_idx) ;
1385
1407
1386
1408
return ;
@@ -1411,10 +1433,25 @@ where
1411
1433
1 => {
1412
1434
// Final payload, parse failure msg.
1413
1435
let cursor = & mut Cursor :: new ( message) ;
1414
- res = Some ( Readable :: read ( cursor) . unwrap ( ) ) ;
1436
+ res = Some ( AttributableFailure {
1437
+ failure_index : route_hop_idx,
1438
+ result : AttributableFailureResult :: Success ( AttributableFailureSuccess {
1439
+ message : Readable :: read ( cursor) . unwrap ( ) ,
1440
+
1441
+ // TODO: Read hold times
1442
+ hold_times : Vec :: new ( ) ,
1443
+ } )
1444
+ } )
1415
1445
}
1416
1446
_ => {
1417
- panic ! ( "Got a payload type we don't know how to handle!" ) ;
1447
+ res = Some ( AttributableFailure {
1448
+ failure_index : route_hop_idx,
1449
+ result : AttributableFailureResult :: InvalidPayload ,
1450
+ } ) ;
1451
+
1452
+ log_debug ! ( logger, "Invalid payload at pos {}" , route_hop_idx) ;
1453
+
1454
+ return ;
1418
1455
}
1419
1456
}
1420
1457
} ;
@@ -1428,7 +1465,17 @@ where
1428
1465
)
1429
1466
. expect ( "Route we used spontaneously grew invalid keys in the middle of it?" ) ;
1430
1467
1431
- res
1468
+ match res {
1469
+ Some ( res) => res,
1470
+ None => {
1471
+ // All hmacs checked out, but none was a final payload. The final hop apparently returned an intermediate
1472
+ // payload.
1473
+ AttributableFailure {
1474
+ failure_index : path. hops . len ( ) ,
1475
+ result : AttributableFailureResult :: InvalidPayload ,
1476
+ }
1477
+ }
1478
+ }
1432
1479
}
1433
1480
1434
1481
#[ derive( Clone ) ] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
@@ -2329,6 +2376,28 @@ use crate::util::test_utils::TestLogger;
2329
2376
2330
2377
#[ test]
2331
2378
fn test_attributable_failure_packet_onion ( ) {
2379
+ const EXPECT_FAILURE : & str = "400f0000000000000064000c3500fd84d1fd012c808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080" ;
2380
+
2381
+ for mutating_node in 0 ..5 {
2382
+ for mutated_index in 0 ..1968 {
2383
+ println ! ( "Testing mutation {} on node {}" , mutated_index, mutating_node) ;
2384
+
2385
+ let decrypted_failure = test_attributable_failure_packet_onion_with_mutation ( mutating_node, mutated_index) ;
2386
+
2387
+ match decrypted_failure. result {
2388
+ AttributableFailureResult :: Success ( success) => {
2389
+ assert_eq ! ( success. message. to_lower_hex_string( ) , EXPECT_FAILURE ) ;
2390
+ assert_eq ! ( decrypted_failure. failure_index, 4 ) ;
2391
+ }
2392
+ AttributableFailureResult :: InvalidPayload | AttributableFailureResult :: InvalidHmac => {
2393
+ assert_eq ! ( decrypted_failure. failure_index, 4 -mutating_node) ;
2394
+ }
2395
+ }
2396
+ }
2397
+ }
2398
+ }
2399
+
2400
+ fn test_attributable_failure_packet_onion_with_mutation ( mutating_node : usize , mutated_index : usize ) -> AttributableFailure {
2332
2401
const FAILURE_DATA : & str = "0000000000000064000c3500fd84d1fd012c808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080" ;
2333
2402
const EXPECTED_MESSAGES : [ & str ; 5 ] = [
2334
2403
"e88935bf7c9a374ba64fd9da3aa2a05e6cf9e52cfb1f72698fd33b74b9c79346284931ea3571af54de5df341304833b0825fb7e8817fd82a29c0803f0a0679a6a073c33a6fb8250090a3152eba3f11a85184fa87b67f1b0354d6f48e3b342e332a17b7710f342f342a87cf32eccdf0afc2160808d58abb5e5840d2c760c538e63a6f841970f97d2e6fe5b8739dc45e2f7f5f532f227bcc2988ab0f9cc6d3f12909cd5842c37bc8c7608475a5ebbe10626d5ecc1f3388ad5f645167b44a4d166f87863fe34918cea25c18059b4c4d9cb414b59f6bc50c1cea749c80c43e2344f5d23159122ed4ab9722503b212016470d9610b46c35dbeebaf2e342e09770b38392a803bc9d2e7c8d6d384ffcbeb74943fe3f64afb2a543a6683c7db3088441c531eeb4647518cb41992f8954f1269fb969630944928c2d2b45593731b5da0c4e70d0c84ad72f642fc26919927b347808bade4b1c321b08bc363f20745ba2f97f0ced2996a232f55ba28fe7dfa70a9ab0433a085388f25cce8d53de6a2fbd7546377d6ede9027ad173ba1f95767461a3689ef405ab608a21086165c64b02c1782b04a6dba2361a7784603069124e12f2f6dcb1ec7612a4fbf94c0e14631a2bef6190c3d5f35e0c4b32aa85201f449d830fd8f782ec758b0910428e3ec3ca1dba3b6c7d89f69e1ee1b9df3dfbbf6d361e1463886b38d52e8f43b73a3bd48c6f36f5897f514b93364a31d49d1d506340b1315883d425cb36f4ea553430d538fd6f3596d4afc518db2f317dd051abc0d4bfb0a7870c3db70f19fe78d6604bbf088fcb4613f54e67b038277fedcd9680eb97bdffc3be1ab2cbcbafd625b8a7ac34d8c190f98d3064ecd3b95b8895157c6a37f31ef4de094b2cb9dbf8ff1f419ba0ecacb1bb13df0253b826bec2ccca1e745dd3b3e7cc6277ce284d649e7b8285727735ff4ef6cca6c18e2714f4e2a1ac67b25213d3bb49763b3b94e7ebf72507b71fb2fe0329666477ee7cb7ebd6b88ad5add8b217188b1ca0fa13de1ec09cc674346875105be6e0e0d6c8928eb0df23c39a639e04e4aedf535c4e093f08b2c905a14f25c0c0fe47a5a1535ab9eae0d9d67bdd79de13a08d59ee05385c7ea4af1ad3248e61dd22f8990e9e99897d653dd7b1b1433a6d464ea9f74e377f2d8ce99ba7dbc753297644234d25ecb5bd528e2e2082824681299ac30c05354baaa9c3967d86d7c07736f87fc0f63e5036d47235d7ae12178ced3ae36ee5919c093a02579e4fc9edad2c446c656c790704bfc8e2c491a42500aa1d75c8d4921ce29b753f883e17c79b09ea324f1f32ddf1f3284cd70e847b09d90f6718c42e5c94484cc9cbb0df659d255630a3f5a27e7d5dd14fa6b974d1719aa98f01a20fb4b7b1c77b42d57fab3c724339d459ee4a1c6b5d3bd4e08624c786a257872acc9ad3ff62222f2265a658d9e2a007228a5293b67ec91c84c4b4407c228434bad8a815ca9b256c776bd2c9f92e2cf87a89ed786194104eba6b7973491f04d0b924c10e6fcff336d037b6e53fe763919da946a640960978994e8d0e5a2d555c9a897ce38a324c766fd01e9416acd91f1ea345c12aa1cfa5933c5c1230c5e45efb8c7e8d75bd9dd85ce8228cf80a52c915282375663690d1286ba0e70201af791a25715819dfd1035feb5239e3df7c230956cb3be858395094d3d99cbc2352cb8adc7a8fe8f4755a2f93bef3926f57bbcff17956c4031a2ae8c88d57dd9235b49a0253e86a7f173d96907aa2e162c82f1626dd5c07188e5e01d79724a546bed2b89a2084230b770ff97b2271158569ed7d00f967cdc51d216fa1578a9624f9142d8de1039b5d4f51de09324c91582f830c7730934feffbc7c51d5d87e8760a77e0712d947190ea6f896a4685045a3de3b8187490ee65f68a9c40cf708e03ab5f28a3b7e5e4a164c3cdb3a7a393b120a2306671a3e310419f873e1d978ff08535353a85eb1773e7476f1f102e3f2364036427a633d32cbf1c34ee0a223f696e69d9e296ac4981d64c99e9966d93eef673163ac774b2545e36e64816030b4ebb7775afeb77f88396c565d58bf2f2d07601dfc5338e5a5a71853dac2e42fc2d89a2da7bf913a8d5c1705ef3c869dc6a7d3a6a8ec7cde4e99380c0223b8d766506574f45cafbe96b25ebefd066945bffc1d2262d1e7d1057660ec2916055a493f2930afe8133de9e593b470e2d512ab5bedb363a6c9ac59fd82379f528d02bae1ade38fafe2d7ac7b097bb6fa4e00e43b087d3480f41402a5156379052526827da75486cf8703ed9ba34f38a9b445da35c3e5bd799156f25081e88051d54fe47fd0f7bca364d7cdeb01cb28aadc9b03fdd91712036f1da31a554e230a897e7142c0043c98e1d9a4bd996d26dfbce431bce8a6e29048783a7142c84483895c44df5d65c3bf8ca1bd6069ad305e525df7a4c584299525549bd3d013dcbfaebf18dcd82a9d29618a9b3e564b19cfdeac6eb7a6c4ad42268747fbd162c2f300aaad722d59dde7db179d93468b435724d97078df797d75d1728e75d0687e661fb603fa1b264466b8cedb75482ef042151f2ca045c795683a5e56dfff85a17f82cc5aba7e187784f159a996c3200b8b3f2a91de25d378557c5b33f2a17ec877b15cccc5615836899c30912cb83390e24902cbecb57cb95c0738d798debc43a07b09060347b145d5ccc150fcc46bc0a21f372622f25acae867946346e54498737be61c312e93086748b37633cbd8ab62433e6375914f117b9c1cb802513f" ,
@@ -2351,23 +2420,33 @@ use crate::util::test_utils::TestLogger;
2351
2420
let mut packet = onion_error. encode ( ) ;
2352
2421
let packet_slice = packet. as_mut_slice ( ) ;
2353
2422
2423
+ let logger: Arc < TestLogger > = Arc :: new ( TestLogger :: new ( ) ) ;
2424
+ log_info ! ( logger, "packet len: {}" , packet_slice. len( ) ) ;
2425
+
2354
2426
super :: add_hmacs ( onion_keys[ 4 ] . shared_secret . as_ref ( ) , packet_slice) ;
2355
2427
2428
+ if mutating_node == 0 {
2429
+ packet_slice[ mutated_index] ^= 1 ;
2430
+ }
2431
+
2356
2432
let mut encrypted_packet = super :: encrypt_failure_packet ( onion_keys[ 4 ] . shared_secret . as_ref ( ) , packet_slice) ;
2357
- assert_eq ! ( encrypted_packet. data. to_lower_hex_string( ) , EXPECTED_MESSAGES [ 0 ] ) ;
2433
+ // assert_eq!(encrypted_packet.data.to_lower_hex_string(), EXPECTED_MESSAGES[0]);
2358
2434
2359
2435
for idx in 1 ..5 {
2436
+
2360
2437
let shared_secret = onion_keys[ 4 - idx] . shared_secret . as_ref ( ) ;
2361
2438
2362
2439
let payload = [ 0 , 0 , 0 , ( idx + 1 ) as u8 ] ;
2363
2440
let processed_packet = process_failure_packet ( & encrypted_packet. data , shared_secret, & payload) ;
2364
2441
encrypted_packet = super :: encrypt_failure_packet ( shared_secret, & processed_packet) ;
2365
2442
2366
- assert_eq ! ( encrypted_packet. data. to_lower_hex_string( ) , EXPECTED_MESSAGES [ idx] ) ;
2443
+ if idx == mutating_node {
2444
+ encrypted_packet. data [ mutated_index] ^= 1 ;
2445
+ }
2446
+ // assert_eq!(encrypted_packet.data.to_lower_hex_string(), EXPECTED_MESSAGES[idx]);
2367
2447
}
2368
2448
2369
2449
let ctx_full = Secp256k1 :: new ( ) ;
2370
- let logger = Arc :: new ( TestLogger :: new ( ) ) ;
2371
2450
2372
2451
let path = build_test_path ( ) ;
2373
2452
let session_priv = SecretKey :: from_slice ( <Vec < u8 > >:: from_hex ( SESSION_KEY ) . unwrap ( ) . as_slice ( ) ) . unwrap ( ) ;
@@ -2378,8 +2457,11 @@ use crate::util::test_utils::TestLogger;
2378
2457
payment_id : PaymentId ( [ 1 ; 32 ] )
2379
2458
, } ;
2380
2459
2460
+
2381
2461
// Assert that the original failure can be retrieved and that all hmacs check out.
2382
- let decrypted_failure = process_attributable_onion_failure ( & ctx_full, & logger, & htlc_source, encrypted_packet. data ) . unwrap ( ) ;
2383
- assert_eq ! ( onion_error. failuremsg, decrypted_failure) ;
2462
+ let decrypted_failure = process_attributable_onion_failure ( & ctx_full, & logger, & htlc_source, encrypted_packet. data ) ;
2463
+
2464
+ decrypted_failure
2465
+
2384
2466
}
2385
2467
}
0 commit comments