Skip to content

Commit

Permalink
Blame outbound channel on UPDATE onion failure with 0-len update
Browse files Browse the repository at this point in the history
We've run into this several times in the wild, likely due to
ElementsProject/lightning#6200 wherein a node on the
path will error with 0x1000 but not provide a channel update (a spec
violation).

Previously, we would blame the inbound edge even though the buggy peer wanted
us to blame the outbound edge. Since this issue seems to be recurring and our
blaming the inbound edge is causing us to punish innocent channels, trust the
peer that the outbound edge is the one to blame.
  • Loading branch information
valentinewallace committed Sep 15, 2023
1 parent daff249 commit 697150c
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
30 changes: 28 additions & 2 deletions lightning/src/ln/onion_route_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,34 @@ fn test_onion_failure() {
}, || nodes[2].node.fail_htlc_backwards(&payment_hash), false, None,
Some(NetworkUpdate::NodeFailure { node_id: route.paths[0].hops[1].pubkey, is_permanent: true }),
Some(channels[1].0.contents.short_channel_id));
run_onion_failure_test_with_fail_intercept("0-length channel update in UPDATE onion failure", 200, &nodes,
&route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
run_onion_failure_test_with_fail_intercept("0-length channel update in intermediate node UPDATE onion failure",
100, &nodes, &route, &payment_hash, &payment_secret, |msg| {
msg.amount_msat -= 1;
}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
let mut decoded_err_packet = msgs::DecodedOnionErrorPacket {
failuremsg: vec![
0x10, 0x7, // UPDATE|7
0x0, 0x0 // 0-len channel update
],
pad: vec![0; 255 - 4 /* 4-byte error message */],
hmac: [0; 32],
};
let um = onion_utils::gen_um_from_shared_secret(&onion_keys[0].shared_secret.as_ref());
let mut hmac = HmacEngine::<Sha256>::new(&um);
hmac.input(&decoded_err_packet.encode()[32..]);
decoded_err_packet.hmac = Hmac::from_engine(hmac).into_inner();
msg.reason = onion_utils::encrypt_failure_packet(
&onion_keys[0].shared_secret.as_ref(), &decoded_err_packet.encode()[..])
}, || {}, true, Some(0x1000|7),
Some(NetworkUpdate::ChannelFailure {
short_channel_id: channels[1].0.contents.short_channel_id,
is_permanent: false,
}),
Some(channels[1].0.contents.short_channel_id));
run_onion_failure_test_with_fail_intercept("0-length channel update in final node UPDATE onion failure",
200, &nodes, &route, &payment_hash, &payment_secret, |_msg| {}, |msg| {
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
let mut decoded_err_packet = msgs::DecodedOnionErrorPacket {
Expand Down
3 changes: 2 additions & 1 deletion lightning/src/ln/onion_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,8 +639,9 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(
} else {
// The node in question intentionally encoded a 0-length channel update. This is
// likely due to https://github.com/ElementsProject/lightning/issues/6200.
short_channel_id = Some(failing_route_hop.short_channel_id);
network_update = Some(NetworkUpdate::ChannelFailure {
short_channel_id: route_hop.short_channel_id,
short_channel_id: failing_route_hop.short_channel_id,
is_permanent: false,
});
}
Expand Down

0 comments on commit 697150c

Please sign in to comment.