Skip to content

Commit 2613fa0

Browse files
committed
Propagate Trampoline blinding errors
When a blinded hop fails to decode, we send a special malformed error. However, we previously simply checked the presence of a blinding point within the `UpdateAddHTLC` message, which is not necessarily applicable to Trampoline, so now we additionally return a flag if the error stemmed from an inner onion's blinded hop decoding failure.
1 parent 7b05135 commit 2613fa0

File tree

3 files changed

+62
-27
lines changed

3 files changed

+62
-27
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5984,7 +5984,7 @@ where
59845984
onion_packet.hmac, payment_hash, None, &*self.node_signer
59855985
) {
59865986
Ok(res) => res,
5987-
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
5987+
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code, .. }) => {
59885988
let sha256_of_onion = Sha256::hash(&onion_packet.hop_data).to_byte_array();
59895989
// In this scenario, the phantom would have sent us an
59905990
// `update_fail_malformed_htlc`, meaning here we encrypt the error as

lightning/src/ln/onion_payment.rs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -473,27 +473,23 @@ where
473473
NS::Target: NodeSigner,
474474
L::Target: Logger,
475475
{
476-
macro_rules! return_malformed_err {
477-
($msg: expr, $err_code: expr) => {
478-
{
479-
log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
480-
let (sha256_of_onion, failure_code) = if msg.blinding_point.is_some() {
481-
([0; 32], INVALID_ONION_BLINDING)
482-
} else {
483-
(Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(), $err_code)
484-
};
485-
return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
486-
channel_id: msg.channel_id,
487-
htlc_id: msg.htlc_id,
488-
sha256_of_onion,
489-
failure_code,
490-
}));
491-
}
492-
}
493-
}
476+
let encode_malformed_error = |message: &str, err_code: u16| {
477+
log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message);
478+
let (sha256_of_onion, failure_code) = if msg.blinding_point.is_some() || err_code == INVALID_ONION_BLINDING {
479+
([0; 32], INVALID_ONION_BLINDING)
480+
} else {
481+
(Sha256::hash(&msg.onion_routing_packet.hop_data).to_byte_array(), err_code)
482+
};
483+
return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
484+
channel_id: msg.channel_id,
485+
htlc_id: msg.htlc_id,
486+
sha256_of_onion,
487+
failure_code,
488+
}));
489+
};
494490

495491
if let Err(_) = msg.onion_routing_packet.public_key {
496-
return_malformed_err!("invalid ephemeral pubkey", 0x8000 | 0x4000 | 6);
492+
return encode_malformed_error("invalid ephemeral pubkey", 0x8000 | 0x4000 | 6);
497493
}
498494

499495
if msg.onion_routing_packet.version != 0 {
@@ -503,12 +499,12 @@ where
503499
//receiving node would have to brute force to figure out which version was put in the
504500
//packet by the node that send us the message, in the case of hashing the hop_data, the
505501
//node knows the HMAC matched, so they already know what is there...
506-
return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4);
502+
return encode_malformed_error("Unknown onion packet version", 0x8000 | 0x4000 | 4);
507503
}
508504

509505
let encode_relay_error = |message: &str, err_code: u16, shared_secret: [u8; 32], trampoline_shared_secret: Option<[u8; 32]>, data: &[u8]| {
510506
if msg.blinding_point.is_some() {
511-
return_malformed_err!(message, INVALID_ONION_BLINDING)
507+
return encode_malformed_error(message, INVALID_ONION_BLINDING)
512508
}
513509

514510
log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message);
@@ -527,7 +523,7 @@ where
527523
) {
528524
Ok(res) => res,
529525
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
530-
return_malformed_err!(err_msg, err_code);
526+
return encode_malformed_error(err_msg, err_code);
531527
},
532528
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret, trampoline_shared_secret }) => {
533529
return encode_relay_error(err_msg, err_code, shared_secret.secret_bytes(), trampoline_shared_secret.map(|tss| tss.secret_bytes()), &[0; 0]);

lightning/src/ln/onion_utils.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,15 +1828,54 @@ where
18281828
trampoline_shared_secret,
18291829
),
18301830
}),
1831-
Ok((_, None)) => Err(OnionDecodeErr::Malformed {
1831+
Ok((msgs::InboundTrampolinePayload::BlindedForward(hop_data), None)) => {
1832+
if hop_data.intro_node_blinding_point.is_some() {
1833+
return Err(OnionDecodeErr::Relay {
1834+
err_msg: "Non-final intro node Trampoline onion data provided to us as last hop",
1835+
err_code: 0x4000 | 22,
1836+
shared_secret,
1837+
trampoline_shared_secret: Some(SharedSecret::from_bytes(
1838+
trampoline_shared_secret,
1839+
)),
1840+
});
1841+
}
1842+
Err(OnionDecodeErr::Malformed {
1843+
err_msg: "Non-final Trampoline onion data provided to us as last hop",
1844+
err_code: INVALID_ONION_BLINDING,
1845+
})
1846+
},
1847+
Ok((msgs::InboundTrampolinePayload::BlindedReceive(hop_data), Some(_))) => {
1848+
if hop_data.intro_node_blinding_point.is_some() {
1849+
return Err(OnionDecodeErr::Relay {
1850+
err_msg: "Final Trampoline intro node onion data provided to us as intermediate hop",
1851+
err_code: 0x4000 | 22,
1852+
shared_secret,
1853+
trampoline_shared_secret: Some(SharedSecret::from_bytes(
1854+
trampoline_shared_secret,
1855+
)),
1856+
});
1857+
}
1858+
Err(OnionDecodeErr::Malformed {
1859+
err_msg:
1860+
"Final Trampoline onion data provided to us as intermediate hop",
1861+
err_code: INVALID_ONION_BLINDING,
1862+
})
1863+
},
1864+
Ok((_, None)) => Err(OnionDecodeErr::Relay {
18321865
err_msg: "Non-final Trampoline onion data provided to us as last hop",
1833-
// todo: find more suitable error code
18341866
err_code: 0x4000 | 22,
1867+
shared_secret,
1868+
trampoline_shared_secret: Some(SharedSecret::from_bytes(
1869+
trampoline_shared_secret,
1870+
)),
18351871
}),
1836-
Ok((_, Some(_))) => Err(OnionDecodeErr::Malformed {
1872+
Ok((_, Some(_))) => Err(OnionDecodeErr::Relay {
18371873
err_msg: "Final Trampoline onion data provided to us as intermediate hop",
1838-
// todo: find more suitable error code
18391874
err_code: 0x4000 | 22,
1875+
shared_secret,
1876+
trampoline_shared_secret: Some(SharedSecret::from_bytes(
1877+
trampoline_shared_secret,
1878+
)),
18401879
}),
18411880
Err(e) => Err(e),
18421881
}

0 commit comments

Comments
 (0)