Merge pull request #1779 from valentinewallace/2022-10-node-pk-keysinterface
[rust-lightning] / lightning / src / ln / onion_utils.rs
index 3795ad5ee77d70a03e5124fc3800823f610e0634..598edcf0367952b011e290bfe48938ec92364ecb 100644 (file)
@@ -7,16 +7,16 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-use ln::channelmanager::HTLCSource;
-use ln::msgs;
-use ln::wire::Encode;
-use routing::gossip::NetworkUpdate;
-use routing::router::RouteHop;
-use util::chacha20::{ChaCha20, ChaChaReader};
-use util::errors::{self, APIError};
-use util::ser::{Readable, ReadableArgs, Writeable, LengthCalculatingWriter};
-use util::logger::Logger;
+use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+use crate::ln::channelmanager::HTLCSource;
+use crate::ln::msgs;
+use crate::ln::wire::Encode;
+use crate::routing::gossip::NetworkUpdate;
+use crate::routing::router::RouteHop;
+use crate::util::chacha20::{ChaCha20, ChaChaReader};
+use crate::util::errors::{self, APIError};
+use crate::util::ser::{Readable, ReadableArgs, Writeable, LengthCalculatingWriter};
+use crate::util::logger::Logger;
 
 use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::cmp::fixed_time_eq;
@@ -28,8 +28,8 @@ use bitcoin::secp256k1::Secp256k1;
 use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::secp256k1;
 
-use prelude::*;
-use io::{Cursor, Read};
+use crate::prelude::*;
+use crate::io::{Cursor, Read};
 use core::convert::{AsMut, TryInto};
 use core::ops::Deref;
 
@@ -425,6 +425,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
 
                                if fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &err_packet.hmac) {
                                        if let Some(error_code_slice) = err_packet.failuremsg.get(0..2) {
+                                               const BADONION: u16 = 0x8000;
                                                const PERM: u16 = 0x4000;
                                                const NODE: u16 = 0x2000;
                                                const UPDATE: u16 = 0x1000;
@@ -445,12 +446,24 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                let mut network_update = None;
                                                let mut short_channel_id = None;
 
-                                               if error_code & NODE == NODE {
+                                               if error_code & BADONION == BADONION {
+                                                       // If the error code has the BADONION bit set, always blame the channel
+                                                       // from the node "originating" the error to its next hop. The
+                                                       // "originator" is ultimately actually claiming that its counterparty
+                                                       // is the one who is failing the HTLC.
+                                                       // If the "originator" here isn't lying we should really mark the
+                                                       // next-hop node as failed entirely, but we can't be confident in that,
+                                                       // as it would allow any node to get us to completely ban one of its
+                                                       // counterparties. Instead, we simply remove the channel in question.
+                                                       network_update = Some(NetworkUpdate::ChannelFailure {
+                                                               short_channel_id: failing_route_hop.short_channel_id,
+                                                               is_permanent: true,
+                                                       });
+                                               } else if error_code & NODE == NODE {
                                                        let is_permanent = error_code & PERM == PERM;
                                                        network_update = Some(NetworkUpdate::NodeFailure { node_id: route_hop.pubkey, is_permanent });
                                                        short_channel_id = Some(route_hop.short_channel_id);
-                                               }
-                                               else if error_code & PERM == PERM {
+                                               } else if error_code & PERM == PERM {
                                                        if !payment_failed {
                                                                network_update = Some(NetworkUpdate::ChannelFailure {
                                                                        short_channel_id: failing_route_hop.short_channel_id,
@@ -458,8 +471,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                                });
                                                                short_channel_id = Some(failing_route_hop.short_channel_id);
                                                        }
-                                               }
-                                               else if error_code & UPDATE == UPDATE {
+                                               } else if error_code & UPDATE == UPDATE {
                                                        if let Some(update_len_slice) = err_packet.failuremsg.get(debug_field_size+2..debug_field_size+4) {
                                                                let update_len = u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
                                                                if let Some(mut update_slice) = err_packet.failuremsg.get(debug_field_size + 4..debug_field_size + 4 + update_len) {
@@ -545,9 +557,6 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                        short_channel_id = Some(route_hop.short_channel_id);
                                                }
 
-                                               // TODO: Here (and a few other places) we assume that BADONION errors
-                                               // are always "sourced" from the node previous to the one which failed
-                                               // to decode the onion.
                                                res = Some((network_update, short_channel_id, !(error_code & PERM == PERM && is_from_final_node)));
 
                                                let (description, title) = errors::get_onion_error_description(error_code);
@@ -747,13 +756,13 @@ pub(crate) fn decode_next_hop<D: DecodeInput, R: ReadableArgs<D::Arg>, N: NextPa
 
 #[cfg(test)]
 mod tests {
-       use io;
-       use prelude::*;
-       use ln::PaymentHash;
-       use ln::features::{ChannelFeatures, NodeFeatures};
-       use routing::router::{Route, RouteHop};
-       use ln::msgs;
-       use util::ser::{Writeable, Writer};
+       use crate::io;
+       use crate::prelude::*;
+       use crate::ln::PaymentHash;
+       use crate::ln::features::{ChannelFeatures, NodeFeatures};
+       use crate::routing::router::{Route, RouteHop};
+       use crate::ln::msgs;
+       use crate::util::ser::{Writeable, Writer};
 
        use hex;