Skip to content

Commit ca33379

Browse files
Parse onion error codes that occurred within blinded paths
When parsing an onion failure, we need to set error code/data and is_from_final_node if an error occurred in a blinded path, for debugging and for Payment{Path}Failed events.
1 parent c6b142e commit ca33379

File tree

1 file changed

+35
-20
lines changed

1 file changed

+35
-20
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -419,14 +419,6 @@ where L::Target: Logger {
419419
{
420420
if res.is_some() { return; }
421421

422-
let route_hop = match route_hop_opt {
423-
Some(hop) => hop,
424-
None => return,
425-
};
426-
427-
let amt_to_forward = htlc_msat - route_hop.fee_msat;
428-
htlc_msat = amt_to_forward;
429-
430422
let ammag = gen_ammag_from_shared_secret(shared_secret.as_ref());
431423

432424
let mut decryption_tmp = Vec::with_capacity(packet_decrypted.len());
@@ -435,11 +427,6 @@ where L::Target: Logger {
435427
chacha.process(&packet_decrypted, &mut decryption_tmp[..]);
436428
packet_decrypted = decryption_tmp;
437429

438-
// The failing hop includes either the inbound channel to the recipient or the outbound channel
439-
// from the current hop (i.e., the next hop's inbound channel).
440-
is_from_final_node = route_hop_idx + 1 == path.hops.len();
441-
let failing_route_hop = if is_from_final_node { route_hop } else { &path.hops[route_hop_idx + 1] };
442-
443430
let err_packet = match msgs::DecodedOnionErrorPacket::read(&mut Cursor::new(&packet_decrypted)) {
444431
Ok(p) => p,
445432
Err(_) => return
@@ -448,30 +435,58 @@ where L::Target: Logger {
448435
let mut hmac = HmacEngine::<Sha256>::new(&um);
449436
hmac.input(&err_packet.encode()[32..]);
450437

438+
// The failing hop includes either the inbound channel to the recipient or the outbound channel
439+
// from the current hop (i.e., the next hop's inbound channel).
440+
let num_blinded_hops = path.blinded_tail.as_ref().map_or(0, |t| t.hops.len());
441+
is_from_final_node = route_hop_idx + 1 == path.hops.len() &&
442+
(path.blinded_tail.is_none() || num_blinded_hops == 1);
443+
451444
if !fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &err_packet.hmac) { return }
452445
let error_code_slice = match err_packet.failuremsg.get(0..2) {
453446
Some(s) => s,
454-
None => {
447+
None if route_hop_opt.is_some() => {
455448
// Useless packet that we can't use but it passed HMAC, so it definitely came from the peer
456449
// in question
457450
let network_update = Some(NetworkUpdate::NodeFailure {
458-
node_id: route_hop.pubkey,
451+
node_id: route_hop_opt.as_ref().unwrap().pubkey,
459452
is_permanent: true,
460453
});
461-
let short_channel_id = Some(route_hop.short_channel_id);
454+
let short_channel_id = Some(route_hop_opt.as_ref().unwrap().short_channel_id);
462455
res = Some((network_update, short_channel_id, !is_from_final_node));
463456
return
457+
},
458+
None => return, // Useless packet from a blinded path hop
459+
};
460+
461+
let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2"));
462+
error_code_ret = Some(error_code);
463+
error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
464+
465+
let route_hop = match route_hop_opt {
466+
Some(hop) => hop,
467+
None => {
468+
res = Some((None, None, true));
469+
return
470+
}
471+
};
472+
let failing_route_hop = if is_from_final_node { route_hop } else {
473+
match path.hops.get(route_hop_idx + 1) {
474+
Some(hop) => hop,
475+
None => {
476+
res = Some((None, None, true));
477+
return
478+
}
464479
}
465480
};
481+
482+
let amt_to_forward = htlc_msat - route_hop.fee_msat;
483+
htlc_msat = amt_to_forward;
484+
466485
const BADONION: u16 = 0x8000;
467486
const PERM: u16 = 0x4000;
468487
const NODE: u16 = 0x2000;
469488
const UPDATE: u16 = 0x1000;
470489

471-
let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2"));
472-
error_code_ret = Some(error_code);
473-
error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
474-
475490
let (debug_field, debug_field_size) = errors::get_onion_debug_field(error_code);
476491

477492
// indicate that payment parameter has failed and no need to update Route object

0 commit comments

Comments
 (0)