// 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;
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::secp256k1::{SecretKey,PublicKey};
+use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar};
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;
Hmac::from_engine(hmac).into_inner()
}
-pub(crate) fn next_hop_packet_pubkey<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, mut packet_pubkey: PublicKey, packet_shared_secret: &[u8; 32]) -> Result<PublicKey, secp256k1::Error> {
+pub(crate) fn next_hop_packet_pubkey<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, packet_pubkey: PublicKey, packet_shared_secret: &[u8; 32]) -> Result<PublicKey, secp256k1::Error> {
let blinding_factor = {
let mut sha = Sha256::engine();
sha.input(&packet_pubkey.serialize()[..]);
Sha256::from_engine(sha).into_inner()
};
- packet_pubkey.mul_assign(secp_ctx, &blinding_factor[..]).map(|_| packet_pubkey)
+ packet_pubkey.mul_tweak(secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap())
}
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
let ephemeral_pubkey = blinded_pub;
- blinded_priv.mul_assign(&blinding_factor)?;
+ blinded_priv = blinded_priv.mul_tweak(&Scalar::from_be_bytes(blinding_factor).unwrap())?;
blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
callback(shared_secret, blinding_factor, ephemeral_pubkey, hop, idx);
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;
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,
});
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) {
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);
#[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;