Skip to content

Commit 6b1b176

Browse files
Parse onion error codes that occurred within blinded paths
1 parent df16d2a commit 6b1b176

File tree

1 file changed

+35
-20
lines changed

1 file changed

+35
-20
lines changed

lightning/src/ln/onion_utils.rs

+35-20
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,6 @@ where L::Target: Logger {
413413
{
414414
if res.is_some() { return; }
415415

416-
let route_hop = match route_hop_opt {
417-
Some(hop) => hop,
418-
None => return,
419-
};
420-
421-
let amt_to_forward = htlc_msat - route_hop.fee_msat;
422-
htlc_msat = amt_to_forward;
423-
424416
let ammag = gen_ammag_from_shared_secret(shared_secret.as_ref());
425417

426418
let mut decryption_tmp = Vec::with_capacity(packet_decrypted.len());
@@ -429,11 +421,6 @@ where L::Target: Logger {
429421
chacha.process(&packet_decrypted, &mut decryption_tmp[..]);
430422
packet_decrypted = decryption_tmp;
431423

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

432+
// The failing hop includes either the inbound channel to the recipient or the outbound channel
433+
// from the current hop (i.e., the next hop's inbound channel).
434+
let num_blinded_hops = path.blinded_tail.as_ref().map_or(0, |t| t.hops.len());
435+
is_from_final_node = route_hop_idx + 1 == path.hops.len() &&
436+
(path.blinded_tail.is_none() || num_blinded_hops == 1);
437+
445438
if !fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &err_packet.hmac) { return }
446439
let error_code_slice = match err_packet.failuremsg.get(0..2) {
447440
Some(s) => s,
448-
None => {
441+
None if route_hop_opt.is_some() => {
449442
// Useless packet that we can't use but it passed HMAC, so it definitely came from the peer
450443
// in question
451444
let network_update = Some(NetworkUpdate::NodeFailure {
452-
node_id: route_hop.pubkey,
445+
node_id: route_hop_opt.as_ref().unwrap().pubkey,
453446
is_permanent: true,
454447
});
455-
let short_channel_id = Some(route_hop.short_channel_id);
448+
let short_channel_id = Some(route_hop_opt.as_ref().unwrap().short_channel_id);
456449
res = Some((network_update, short_channel_id, !is_from_final_node));
457450
return
451+
},
452+
None => return, // Useless packet from a blinded path hop
453+
};
454+
455+
let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2"));
456+
error_code_ret = Some(error_code);
457+
error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
458+
459+
let route_hop = match route_hop_opt {
460+
Some(hop) => hop,
461+
None => {
462+
res = Some((None, None, true));
463+
return
464+
}
465+
};
466+
let failing_route_hop = if is_from_final_node { route_hop } else {
467+
match path.hops.get(route_hop_idx + 1) {
468+
Some(hop) => hop,
469+
None => {
470+
res = Some((None, None, true));
471+
return
472+
}
458473
}
459474
};
475+
476+
let amt_to_forward = htlc_msat - route_hop.fee_msat;
477+
htlc_msat = amt_to_forward;
478+
460479
const BADONION: u16 = 0x8000;
461480
const PERM: u16 = 0x4000;
462481
const NODE: u16 = 0x2000;
463482
const UPDATE: u16 = 0x1000;
464483

465-
let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2"));
466-
error_code_ret = Some(error_code);
467-
error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
468-
469484
let (debug_field, debug_field_size) = errors::get_onion_debug_field(error_code);
470485

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

0 commit comments

Comments
 (0)