From 1e91b4bc286c8588df17a61b8b134bce2a969f99 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 20:42:23 +0000 Subject: [PATCH 01/11] Drop deprecated methods in `invoice_utils` These methods are super trivial to replace with the `ChannelManager` equivalent, so keeping them around for a while doesn't give us anything. --- lightning/src/ln/invoice_utils.rs | 161 +----------------------------- 1 file changed, 3 insertions(+), 158 deletions(-) diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index a8eec347f1f..a3ee6dec517 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -6,16 +6,13 @@ use lightning_invoice::{Description, Bolt11InvoiceDescription, Sha256}; use crate::prelude::*; use bitcoin::hashes::Hash; -use crate::chain; -use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use crate::sign::{Recipient, NodeSigner, SignerProvider, EntropySource}; +use crate::sign::{Recipient, NodeSigner, EntropySource}; use crate::types::payment::PaymentHash; use crate::ln::channel_state::ChannelDetails; -use crate::ln::channelmanager::{Bolt11InvoiceParameters, ChannelManager, PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA, MIN_FINAL_CLTV_EXPIRY_DELTA}; +use crate::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA, MIN_FINAL_CLTV_EXPIRY_DELTA}; use crate::ln::inbound_payment::{create, create_from_hash}; use crate::routing::gossip::RoutingFees; -use crate::routing::router::{RouteHint, RouteHintHop, Router}; -use crate::onion_message::messenger::MessageRouter; +use crate::routing::router::{RouteHint, RouteHintHop}; use crate::util::logger::{Logger, Record}; use bitcoin::secp256k1::PublicKey; use alloc::collections::{btree_map, BTreeMap}; @@ -312,158 +309,6 @@ fn rotate_through_iterators>(mut vecs: Vec) -> impl }) } -#[deprecated(note = "Use ChannelManager::create_bolt11_invoice instead.")] -/// Utility to construct an invoice. Generally, unless you want to do something like a custom -/// cltv_expiry, this is what you should be using to create an invoice. The reason being, this -/// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user -/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify -/// that the payment secret is valid when the invoice is paid. -/// -/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for -/// in excess of the current time. -/// -/// You can specify a custom `min_final_cltv_expiry_delta`, or let LDK default it to -/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. The provided expiry must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. -/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block -/// confirmations during routing. -/// -/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA -pub fn create_invoice_from_channelmanager( - channelmanager: &ChannelManager, amt_msat: Option, - description: String, invoice_expiry_delta_secs: u32, min_final_cltv_expiry_delta: Option, -) -> Result> -where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - MR::Target: MessageRouter, - L::Target: Logger, -{ - let description = Description::new(description).map_err(SignOrCreationError::CreationError)?; - let params = Bolt11InvoiceParameters { - amount_msats: amt_msat, - description: Bolt11InvoiceDescription::Direct(description), - invoice_expiry_delta_secs: Some(invoice_expiry_delta_secs), - min_final_cltv_expiry_delta, - payment_hash: None, - }; - channelmanager.create_bolt11_invoice(params) -} - -#[deprecated(note = "Use ChannelManager::create_bolt11_invoice instead.")] -/// Utility to construct an invoice. Generally, unless you want to do something like a custom -/// cltv_expiry, this is what you should be using to create an invoice. The reason being, this -/// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user -/// doesn't have to store preimage/payment secret information and (b) `ChannelManager` can verify -/// that the payment secret is valid when the invoice is paid. -/// Use this variant if you want to pass the `description_hash` to the invoice. -/// -/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for -/// in excess of the current time. -/// -/// You can specify a custom `min_final_cltv_expiry_delta`, or let LDK default it to -/// [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. The provided expiry must be at least [`MIN_FINAL_CLTV_EXPIRY_DELTA`]. -/// Note that LDK will add a buffer of 3 blocks to the delta to allow for up to a few new block -/// confirmations during routing. -/// -/// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA -pub fn create_invoice_from_channelmanager_with_description_hash( - channelmanager: &ChannelManager, amt_msat: Option, - description_hash: Sha256, invoice_expiry_delta_secs: u32, - min_final_cltv_expiry_delta: Option, -) -> Result> -where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - MR::Target: MessageRouter, - L::Target: Logger, -{ - let params = Bolt11InvoiceParameters { - amount_msats: amt_msat, - description: Bolt11InvoiceDescription::Hash(description_hash), - invoice_expiry_delta_secs: Some(invoice_expiry_delta_secs), - min_final_cltv_expiry_delta, - payment_hash: None, - }; - channelmanager.create_bolt11_invoice(params) -} - -#[deprecated(note = "Use ChannelManager::create_bolt11_invoice instead.")] -/// See [`create_invoice_from_channelmanager`]. -/// -/// This version allows for providing custom [`PaymentHash`] and description hash for the invoice. -/// -/// This may be useful if you're building an on-chain swap or involving another protocol where -/// the payment hash is also involved outside the scope of lightning and want to set the -/// description hash. -pub fn create_invoice_from_channelmanager_with_description_hash_and_payment_hash( - channelmanager: &ChannelManager, amt_msat: Option, - description_hash: Sha256, invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, - min_final_cltv_expiry_delta: Option, -) -> Result> -where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - MR::Target: MessageRouter, - L::Target: Logger, -{ - let params = Bolt11InvoiceParameters { - amount_msats: amt_msat, - description: Bolt11InvoiceDescription::Hash(description_hash), - invoice_expiry_delta_secs: Some(invoice_expiry_delta_secs), - min_final_cltv_expiry_delta, - payment_hash: Some(payment_hash), - }; - channelmanager.create_bolt11_invoice(params) -} - -#[deprecated(note = "Use ChannelManager::create_bolt11_invoice instead.")] -/// See [`create_invoice_from_channelmanager`]. -/// -/// This version allows for providing a custom [`PaymentHash`] for the invoice. -/// This may be useful if you're building an on-chain swap or involving another protocol where -/// the payment hash is also involved outside the scope of lightning. -pub fn create_invoice_from_channelmanager_with_payment_hash( - channelmanager: &ChannelManager, amt_msat: Option, - description: String, invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, - min_final_cltv_expiry_delta: Option, -) -> Result> -where - M::Target: chain::Watch<::EcdsaSigner>, - T::Target: BroadcasterInterface, - ES::Target: EntropySource, - NS::Target: NodeSigner, - SP::Target: SignerProvider, - F::Target: FeeEstimator, - R::Target: Router, - MR::Target: MessageRouter, - L::Target: Logger, -{ - let description = Description::new(description).map_err(SignOrCreationError::CreationError)?; - let params = Bolt11InvoiceParameters { - amount_msats: amt_msat, - description: Bolt11InvoiceDescription::Direct(description), - invoice_expiry_delta_secs: Some(invoice_expiry_delta_secs), - min_final_cltv_expiry_delta, - payment_hash: Some(payment_hash), - }; - channelmanager.create_bolt11_invoice(params) -} - /// Sorts and filters the `channels` for an invoice, and returns the corresponding `RouteHint`s to include /// in the invoice. /// From b6bf50522b84236699c6affadc89b756c5fd2f26 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 19:16:05 +0000 Subject: [PATCH 02/11] Run rustfmt on `msgs.rs` This leaves some mess in the tests, but they're mostly encoding tests that should never fail and are generally quite short. --- lightning/src/ln/msgs.rs | 1902 ++++++++++++++++++++++++++------------ rustfmt_excluded_files | 1 - 2 files changed, 1316 insertions(+), 587 deletions(-) diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index c27db4a55b4..65ba485c9c5 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -25,43 +25,49 @@ //! track the network on the less-secure system. use bitcoin::constants::ChainHash; -use bitcoin::secp256k1::PublicKey; +use bitcoin::hash_types::Txid; +use bitcoin::script::ScriptBuf; use bitcoin::secp256k1::ecdsa::Signature; +use bitcoin::secp256k1::PublicKey; use bitcoin::{secp256k1, Witness}; -use bitcoin::script::ScriptBuf; -use bitcoin::hash_types::Txid; -use crate::blinded_path::payment::{BlindedPaymentTlvs, ForwardTlvs, ReceiveTlvs, UnauthenticatedReceiveTlvs}; +use crate::blinded_path::payment::{ + BlindedPaymentTlvs, ForwardTlvs, ReceiveTlvs, UnauthenticatedReceiveTlvs, +}; use crate::blinded_path::payment::{BlindedTrampolineTlvs, TrampolineForwardTlvs}; use crate::ln::channelmanager::Verification; -use crate::ln::types::ChannelId; -use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret}; -use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; use crate::ln::onion_utils; +use crate::ln::types::ChannelId; use crate::offers::invoice_request::InvoiceRequest; use crate::onion_message; use crate::sign::{NodeSigner, Recipient}; +use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; #[allow(unused_imports)] use crate::prelude::*; use alloc::collections::BTreeMap; +use crate::io::{self, Cursor, Read}; +use crate::io_extras::read_to_end; use core::fmt; use core::fmt::Debug; +use core::fmt::Display; use core::ops::Deref; #[cfg(feature = "std")] use core::str::FromStr; #[cfg(feature = "std")] use std::net::SocketAddr; -use core::fmt::Display; -use crate::io::{self, Cursor, Read}; -use crate::io_extras::read_to_end; use crate::crypto::streams::ChaChaPolyReadAdapter; -use crate::util::logger; -use crate::util::ser::{BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthLimitedRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, WithoutLength, Writeable, Writer}; use crate::util::base32; +use crate::util::logger; +use crate::util::ser::{ + BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthLimitedRead, + LengthReadable, LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, + WithoutLength, Writeable, Writer, +}; use crate::routing::gossip::{NodeAlias, NodeId}; @@ -71,7 +77,10 @@ pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000; #[cfg(taproot)] /// A partial signature that also contains the Musig2 nonce its signer used #[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct PartialSignatureWithNonce(pub musig2::types::PartialSignature, pub musig2::types::PublicNonce); +pub struct PartialSignatureWithNonce( + pub musig2::types::PartialSignature, + pub musig2::types::PublicNonce, +); /// An error in decoding a message or struct. #[derive(Clone, Debug, Hash, PartialEq, Eq)] @@ -411,7 +420,7 @@ pub struct FundingCreated { pub partial_signature_with_nonce: Option, #[cfg(taproot)] /// Next nonce the channel acceptor should use to finalize the funding output signature - pub next_local_nonce: Option + pub next_local_nonce: Option, } /// A [`funding_signed`] message to be sent to or received from a peer. @@ -704,9 +713,9 @@ pub struct UpdateAddHTLC { pub blinding_point: Option, } - /// An onion message to be sent to or received from a peer. - /// - // TODO: update with link to OM when they are merged into the BOLTs +/// An onion message to be sent to or received from a peer. +/// +// TODO: update with link to OM when they are merged into the BOLTs #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct OnionMessage { /// Used in decrypting the onion packet's payload. @@ -770,7 +779,7 @@ pub struct UpdateFailHTLC { pub(crate) reason: Vec, /// Optional field for the attribution data that allows the sender to pinpoint the failing node under all conditions - pub attribution_data: Option + pub attribution_data: Option, } /// An [`update_fail_malformed_htlc`] message to be sent to or received from a peer. /// @@ -826,7 +835,7 @@ pub struct RevokeAndACK { pub next_per_commitment_point: PublicKey, #[cfg(taproot)] /// Musig nonce the recipient should use in their next commitment signature message - pub next_local_nonce: Option + pub next_local_nonce: Option, } /// An [`update_fee`] message to be sent to or received from a peer @@ -924,23 +933,23 @@ impl SocketAddress { /// by this. pub(crate) fn get_id(&self) -> u8 { match self { - &SocketAddress::TcpIpV4 {..} => { 1 }, - &SocketAddress::TcpIpV6 {..} => { 2 }, - &SocketAddress::OnionV2(_) => { 3 }, - &SocketAddress::OnionV3 {..} => { 4 }, - &SocketAddress::Hostname {..} => { 5 }, + &SocketAddress::TcpIpV4 { .. } => 1, + &SocketAddress::TcpIpV6 { .. } => 2, + &SocketAddress::OnionV2(_) => 3, + &SocketAddress::OnionV3 { .. } => 4, + &SocketAddress::Hostname { .. } => 5, } } /// Strict byte-length of address descriptor, 1-byte type not recorded fn len(&self) -> u16 { match self { - &SocketAddress::TcpIpV4 { .. } => { 6 }, - &SocketAddress::TcpIpV6 { .. } => { 18 }, - &SocketAddress::OnionV2(_) => { 12 }, - &SocketAddress::OnionV3 { .. } => { 37 }, + &SocketAddress::TcpIpV4 { .. } => 6, + &SocketAddress::TcpIpV6 { .. } => 18, + &SocketAddress::OnionV2(_) => 12, + &SocketAddress::OnionV3 { .. } => 37, // Consists of 1-byte hostname length, hostname bytes, and 2-byte port. - &SocketAddress::Hostname { ref hostname, .. } => { u16::from(hostname.len()) + 3 }, + &SocketAddress::Hostname { ref hostname, .. } => u16::from(hostname.len()) + 3, } } @@ -951,11 +960,11 @@ impl SocketAddress { pub(crate) fn is_tor(&self) -> bool { match self { - &SocketAddress::TcpIpV4 {..} => false, - &SocketAddress::TcpIpV6 {..} => false, + &SocketAddress::TcpIpV4 { .. } => false, + &SocketAddress::TcpIpV6 { .. } => false, &SocketAddress::OnionV2(_) => true, - &SocketAddress::OnionV3 {..} => true, - &SocketAddress::Hostname {..} => false, + &SocketAddress::OnionV3 { .. } => true, + &SocketAddress::Hostname { .. } => false, } } } @@ -998,33 +1007,25 @@ impl Readable for Result { fn read(reader: &mut R) -> Result, DecodeError> { let byte = ::read(reader)?; match byte { - 1 => { - Ok(Ok(SocketAddress::TcpIpV4 { - addr: Readable::read(reader)?, - port: Readable::read(reader)?, - })) - }, - 2 => { - Ok(Ok(SocketAddress::TcpIpV6 { - addr: Readable::read(reader)?, - port: Readable::read(reader)?, - })) - }, + 1 => Ok(Ok(SocketAddress::TcpIpV4 { + addr: Readable::read(reader)?, + port: Readable::read(reader)?, + })), + 2 => Ok(Ok(SocketAddress::TcpIpV6 { + addr: Readable::read(reader)?, + port: Readable::read(reader)?, + })), 3 => Ok(Ok(SocketAddress::OnionV2(Readable::read(reader)?))), - 4 => { - Ok(Ok(SocketAddress::OnionV3 { - ed25519_pubkey: Readable::read(reader)?, - checksum: Readable::read(reader)?, - version: Readable::read(reader)?, - port: Readable::read(reader)?, - })) - }, - 5 => { - Ok(Ok(SocketAddress::Hostname { - hostname: Readable::read(reader)?, - port: Readable::read(reader)?, - })) - }, + 4 => Ok(Ok(SocketAddress::OnionV3 { + ed25519_pubkey: Readable::read(reader)?, + checksum: Readable::read(reader)?, + version: Readable::read(reader)?, + port: Readable::read(reader)?, + })), + 5 => Ok(Ok(SocketAddress::Hostname { + hostname: Readable::read(reader)?, + port: Readable::read(reader)?, + })), _ => return Ok(Err(byte)), } } @@ -1067,26 +1068,26 @@ impl fmt::Display for SocketAddressParseError { #[cfg(feature = "std")] impl From for SocketAddress { - fn from(addr: std::net::SocketAddrV4) -> Self { - SocketAddress::TcpIpV4 { addr: addr.ip().octets(), port: addr.port() } - } + fn from(addr: std::net::SocketAddrV4) -> Self { + SocketAddress::TcpIpV4 { addr: addr.ip().octets(), port: addr.port() } + } } #[cfg(feature = "std")] impl From for SocketAddress { - fn from(addr: std::net::SocketAddrV6) -> Self { - SocketAddress::TcpIpV6 { addr: addr.ip().octets(), port: addr.port() } - } + fn from(addr: std::net::SocketAddrV6) -> Self { + SocketAddress::TcpIpV6 { addr: addr.ip().octets(), port: addr.port() } + } } #[cfg(feature = "std")] impl From for SocketAddress { - fn from(addr: std::net::SocketAddr) -> Self { - match addr { - std::net::SocketAddr::V4(addr) => addr.into(), - std::net::SocketAddr::V6(addr) => addr.into(), - } + fn from(addr: std::net::SocketAddr) -> Self { + match addr { + std::net::SocketAddr::V4(addr) => addr.into(), + std::net::SocketAddr::V6(addr) => addr.into(), } + } } #[cfg(feature = "std")] @@ -1099,12 +1100,12 @@ impl std::net::ToSocketAddrs for SocketAddress { let ip_addr = std::net::Ipv4Addr::from(*addr); let socket_addr = SocketAddr::new(ip_addr.into(), *port); Ok(vec![socket_addr].into_iter()) - } + }, SocketAddress::TcpIpV6 { addr, port } => { let ip_addr = std::net::Ipv6Addr::from(*addr); let socket_addr = SocketAddr::new(ip_addr.into(), *port); Ok(vec![socket_addr].into_iter()) - } + }, SocketAddress::Hostname { ref hostname, port } => { (hostname.as_str(), *port).to_socket_addrs() } @@ -1123,13 +1124,17 @@ impl std::net::ToSocketAddrs for SocketAddress { /// Parses an OnionV3 host and port into a [`SocketAddress::OnionV3`]. /// /// The host part must end with ".onion". -pub fn parse_onion_address(host: &str, port: u16) -> Result { +pub fn parse_onion_address( + host: &str, port: u16, +) -> Result { if host.ends_with(".onion") { let domain = &host[..host.len() - ".onion".len()]; if domain.len() != 56 { return Err(SocketAddressParseError::InvalidOnionV3); } - let onion = base32::Alphabet::RFC4648 { padding: false }.decode(&domain).map_err(|_| SocketAddressParseError::InvalidOnionV3)?; + let onion = base32::Alphabet::RFC4648 { padding: false } + .decode(&domain) + .map_err(|_| SocketAddressParseError::InvalidOnionV3)?; if onion.len() != 35 { return Err(SocketAddressParseError::InvalidOnionV3); } @@ -1140,7 +1145,6 @@ pub fn parse_onion_address(host: &str, port: u16) -> Result return Err(SocketAddressParseError::InvalidInput), }; let host = &s[..trimmed_input]; - let port: u16 = s[trimmed_input + 1..].parse().map_err(|_| SocketAddressParseError::InvalidPort)?; + let port: u16 = s[trimmed_input + 1..] + .parse() + .map_err(|_| SocketAddressParseError::InvalidPort)?; if host.ends_with(".onion") { return parse_onion_address(host, port); }; if let Ok(hostname) = Hostname::try_from(s[..trimmed_input].to_string()) { return Ok(SocketAddress::Hostname { hostname, port }); }; - return Err(SocketAddressParseError::SocketAddrParse) + return Err(SocketAddressParseError::SocketAddrParse); }, } } @@ -1208,7 +1214,7 @@ pub enum UnsignedGossipMessage<'a> { /// An unsigned channel update. ChannelUpdate(&'a UnsignedChannelUpdate), /// An unsigned node announcement. - NodeAnnouncement(&'a UnsignedNodeAnnouncement) + NodeAnnouncement(&'a UnsignedNodeAnnouncement), } impl<'a> Writeable for UnsignedGossipMessage<'a> { @@ -1461,7 +1467,7 @@ pub enum ErrorAction { /// The peer took some action which made us think they were useless. Disconnect them. DisconnectPeer { /// An error message which we should make an effort to send before we disconnect. - msg: Option + msg: Option, }, /// The peer did something incorrect. Tell them without closing any channels and disconnect them. DisconnectPeerWithWarning { @@ -1770,7 +1776,7 @@ pub enum MessageSendEvent { /// The node_id of the node which should receive this message node_id: PublicKey, /// The action which should be taken. - action: ErrorAction + action: ErrorAction, }, /// Query a peer for channels with funding transaction UTXOs in a block range. SendChannelRangeQuery { @@ -1819,7 +1825,7 @@ pub enum MessageSendEvent { node_id: PublicKey, /// The peer_storage_retrieval which should be sent. msg: PeerStorageRetrieval, - } + }, } /// A trait to describe an object which handles when peers connect + disconnect and generates @@ -1854,14 +1860,15 @@ pub trait BaseMessageHandler { /// message handlers may still wish to communicate with this peer. /// /// [`Self::peer_disconnected`] will not be called if `Err(())` is returned. - fn peer_connected(&self, their_node_id: PublicKey, msg: &Init, inbound: bool) -> Result<(), ()>; + fn peer_connected(&self, their_node_id: PublicKey, msg: &Init, inbound: bool) + -> Result<(), ()>; } /// A trait to describe an object which can receive channel messages. /// /// Messages MAY be called in parallel when they originate from different `their_node_ids`, however /// they MUST NOT be called in parallel when the two calls have the same `their_node_id`. -pub trait ChannelMessageHandler : BaseMessageHandler { +pub trait ChannelMessageHandler: BaseMessageHandler { // Channel init: /// Handle an incoming `open_channel` message from the given peer. fn handle_open_channel(&self, their_node_id: PublicKey, msg: &OpenChannel); @@ -1933,7 +1940,9 @@ pub trait ChannelMessageHandler : BaseMessageHandler { /// Handle an incoming `update_fail_htlc` message from the given peer. fn handle_update_fail_htlc(&self, their_node_id: PublicKey, msg: &UpdateFailHTLC); /// Handle an incoming `update_fail_malformed_htlc` message from the given peer. - fn handle_update_fail_malformed_htlc(&self, their_node_id: PublicKey, msg: &UpdateFailMalformedHTLC); + fn handle_update_fail_malformed_htlc( + &self, their_node_id: PublicKey, msg: &UpdateFailMalformedHTLC, + ); /// Handle an incoming `commitment_signed` message from the given peer. fn handle_commitment_signed(&self, their_node_id: PublicKey, msg: &CommitmentSigned); /// Handle a batch of incoming `commitment_signed` message from the given peer. @@ -1945,17 +1954,23 @@ pub trait ChannelMessageHandler : BaseMessageHandler { fn handle_revoke_and_ack(&self, their_node_id: PublicKey, msg: &RevokeAndACK); #[cfg(any(test, fuzzing, feature = "_test_utils"))] - fn handle_commitment_signed_batch_test(&self, their_node_id: PublicKey, batch: &Vec) { + fn handle_commitment_signed_batch_test( + &self, their_node_id: PublicKey, batch: &Vec, + ) { assert!(!batch.is_empty()); if batch.len() == 1 { assert!(batch[0].batch.is_none()); self.handle_commitment_signed(their_node_id, &batch[0]); } else { let channel_id = batch[0].channel_id; - let batch: BTreeMap = batch.iter().cloned().map(|mut cs| { - let funding_txid = cs.batch.take().unwrap().funding_txid; - (funding_txid, cs) - }).collect(); + let batch: BTreeMap = batch + .iter() + .cloned() + .map(|mut cs| { + let funding_txid = cs.batch.take().unwrap().funding_txid; + (funding_txid, cs) + }) + .collect(); self.handle_commitment_signed_batch(their_node_id, channel_id, batch); } } @@ -1965,7 +1980,9 @@ pub trait ChannelMessageHandler : BaseMessageHandler { // Channel-to-announce: /// Handle an incoming `announcement_signatures` message from the given peer. - fn handle_announcement_signatures(&self, their_node_id: PublicKey, msg: &AnnouncementSignatures); + fn handle_announcement_signatures( + &self, their_node_id: PublicKey, msg: &AnnouncementSignatures, + ); // Channel reestablish: /// Handle an incoming `channel_reestablish` message from the given peer. @@ -2001,46 +2018,64 @@ pub trait ChannelMessageHandler : BaseMessageHandler { /// For messages enabled with the `gossip_queries` feature there are potential DoS vectors when /// handling inbound queries. Implementors using an on-disk network graph should be aware of /// repeated disk I/O for queries accessing different parts of the network graph. -pub trait RoutingMessageHandler : BaseMessageHandler { +pub trait RoutingMessageHandler: BaseMessageHandler { /// Handle an incoming `node_announcement` message, returning `true` if it should be forwarded on, /// `false` or returning an `Err` otherwise. /// /// If `their_node_id` is `None`, the message was generated by our own local node. - fn handle_node_announcement(&self, their_node_id: Option, msg: &NodeAnnouncement) -> Result; + fn handle_node_announcement( + &self, their_node_id: Option, msg: &NodeAnnouncement, + ) -> Result; /// Handle a `channel_announcement` message, returning `true` if it should be forwarded on, `false` /// or returning an `Err` otherwise. /// /// If `their_node_id` is `None`, the message was generated by our own local node. - fn handle_channel_announcement(&self, their_node_id: Option, msg: &ChannelAnnouncement) -> Result; + fn handle_channel_announcement( + &self, their_node_id: Option, msg: &ChannelAnnouncement, + ) -> Result; /// Handle an incoming `channel_update` message, returning true if it should be forwarded on, /// `false` or returning an `Err` otherwise. /// /// If `their_node_id` is `None`, the message was generated by our own local node. - fn handle_channel_update(&self, their_node_id: Option, msg: &ChannelUpdate) -> Result; + fn handle_channel_update( + &self, their_node_id: Option, msg: &ChannelUpdate, + ) -> Result; /// Gets channel announcements and updates required to dump our routing table to a remote node, /// starting at the `short_channel_id` indicated by `starting_point` and including announcements /// for a single channel. - fn get_next_channel_announcement(&self, starting_point: u64) -> Option<(ChannelAnnouncement, Option, Option)>; + fn get_next_channel_announcement( + &self, starting_point: u64, + ) -> Option<(ChannelAnnouncement, Option, Option)>; /// Gets a node announcement required to dump our routing table to a remote node, starting at /// the node *after* the provided pubkey and including up to one announcement immediately /// higher (as defined by `::cmp`) than `starting_point`. /// If `None` is provided for `starting_point`, we start at the first node. - fn get_next_node_announcement(&self, starting_point: Option<&NodeId>) -> Option; + fn get_next_node_announcement( + &self, starting_point: Option<&NodeId>, + ) -> Option; /// Handles the reply of a query we initiated to learn about channels /// for a given range of blocks. We can expect to receive one or more /// replies to a single query. - fn handle_reply_channel_range(&self, their_node_id: PublicKey, msg: ReplyChannelRange) -> Result<(), LightningError>; + fn handle_reply_channel_range( + &self, their_node_id: PublicKey, msg: ReplyChannelRange, + ) -> Result<(), LightningError>; /// Handles the reply of a query we initiated asking for routing gossip /// messages for a list of channels. We should receive this message when /// a node has completed its best effort to send us the pertaining routing /// gossip messages. - fn handle_reply_short_channel_ids_end(&self, their_node_id: PublicKey, msg: ReplyShortChannelIdsEnd) -> Result<(), LightningError>; + fn handle_reply_short_channel_ids_end( + &self, their_node_id: PublicKey, msg: ReplyShortChannelIdsEnd, + ) -> Result<(), LightningError>; /// Handles when a peer asks us to send a list of `short_channel_id`s /// for the requested range of blocks. - fn handle_query_channel_range(&self, their_node_id: PublicKey, msg: QueryChannelRange) -> Result<(), LightningError>; + fn handle_query_channel_range( + &self, their_node_id: PublicKey, msg: QueryChannelRange, + ) -> Result<(), LightningError>; /// Handles when a peer asks us to send routing gossip messages for a /// list of `short_channel_id`s. - fn handle_query_short_channel_ids(&self, their_node_id: PublicKey, msg: QueryShortChannelIds) -> Result<(), LightningError>; + fn handle_query_short_channel_ids( + &self, their_node_id: PublicKey, msg: QueryShortChannelIds, + ) -> Result<(), LightningError>; // Handler queueing status: /// Indicates that there are a large number of [`ChannelAnnouncement`] (or other) messages @@ -2081,13 +2116,15 @@ pub struct FinalOnionHopData { } mod fuzzy_internal_msgs { - use bitcoin::secp256k1::PublicKey; - use crate::blinded_path::payment::{BlindedPaymentPath, PaymentConstraints, PaymentContext, PaymentRelay}; + use super::{FinalOnionHopData, TrampolineOnionPacket}; + use crate::blinded_path::payment::{ + BlindedPaymentPath, PaymentConstraints, PaymentContext, PaymentRelay, + }; use crate::ln::onion_utils::AttributionData; use crate::offers::invoice_request::InvoiceRequest; - use crate::types::payment::{PaymentPreimage, PaymentSecret}; use crate::types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; - use super::{FinalOnionHopData, TrampolineOnionPacket}; + use crate::types::payment::{PaymentPreimage, PaymentSecret}; + use bitcoin::secp256k1::PublicKey; #[allow(unused_imports)] use crate::prelude::*; @@ -2110,7 +2147,7 @@ mod fuzzy_internal_msgs { pub trampoline_packet: TrampolineOnionPacket, /// The blinding point this hop needs to decrypt its Trampoline onion. /// This is used for Trampoline hops that are not the blinded path intro hop. - pub current_path_key: Option + pub current_path_key: Option, } pub struct InboundOnionReceivePayload { @@ -2196,7 +2233,7 @@ mod fuzzy_internal_msgs { multipath_trampoline_data: Option, trampoline_packet: TrampolineOnionPacket, /// The blinding point this hop needs to use for its Trampoline onion. - current_path_key: PublicKey + current_path_key: PublicKey, }, Receive { payment_data: Option, @@ -2219,7 +2256,7 @@ mod fuzzy_internal_msgs { keysend_preimage: Option, custom_tlvs: &'a Vec<(u64, Vec)>, invoice_request: Option<&'a InvoiceRequest>, - } + }, } pub(crate) enum OutboundTrampolinePayload<'a> { @@ -2263,7 +2300,7 @@ mod fuzzy_internal_msgs { intro_node_blinding_point: Option, // Set if the introduction node of the blinded path is the final node keysend_preimage: Option, custom_tlvs: &'a Vec<(u64, Vec)>, - } + }, } pub struct DecodedOnionErrorPacket { @@ -2299,7 +2336,7 @@ pub struct OnionPacket { /// like. pub public_key: Result, /// 1300 bytes encrypted payload for the next hop. - pub hop_data: [u8; 20*65], + pub hop_data: [u8; 20 * 65], /// HMAC to verify the integrity of hop_data. pub hmac: [u8; 32], } @@ -2307,18 +2344,17 @@ pub struct OnionPacket { impl onion_utils::Packet for OnionPacket { type Data = onion_utils::FixedSizeOnionPacket; fn new(pubkey: PublicKey, hop_data: onion_utils::FixedSizeOnionPacket, hmac: [u8; 32]) -> Self { - Self { - version: 0, - public_key: Ok(pubkey), - hop_data: hop_data.0, - hmac, - } + Self { version: 0, public_key: Ok(pubkey), hop_data: hop_data.0, hmac } } } impl fmt::Debug for OnionPacket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("OnionPacket version {} with hmac {:?}", self.version, &self.hmac[..])) + f.write_fmt(format_args!( + "OnionPacket version {} with hmac {:?}", + self.version, + &self.hmac[..] + )) } } @@ -2343,12 +2379,7 @@ pub struct TrampolineOnionPacket { impl onion_utils::Packet for TrampolineOnionPacket { type Data = Vec; fn new(public_key: PublicKey, hop_data: Vec, hmac: [u8; 32]) -> Self { - Self { - version: 0, - public_key, - hop_data, - hmac, - } + Self { version: 0, public_key, hop_data, hmac } } } @@ -2374,27 +2405,23 @@ impl LengthReadable for TrampolineOnionPacket { let hmac = Readable::read(r)?; - Ok(TrampolineOnionPacket { - version, - public_key, - hop_data, - hmac, - }) + Ok(TrampolineOnionPacket { version, public_key, hop_data, hmac }) } } impl Debug for TrampolineOnionPacket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("TrampolineOnionPacket version {} with hmac {:?}", self.version, &self.hmac[..])) + f.write_fmt(format_args!( + "TrampolineOnionPacket version {} with hmac {:?}", + self.version, + &self.hmac[..] + )) } } impl From for OnionErrorPacket { fn from(msg: UpdateFailHTLC) -> Self { - OnionErrorPacket { - data: msg.reason, - attribution_data: msg.attribution_data, - } + OnionErrorPacket { data: msg.reason, attribution_data: msg.attribution_data } } } @@ -2402,13 +2429,23 @@ impl fmt::Display for DecodeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { DecodeError::UnknownVersion => f.write_str("Unknown realm byte in Onion packet"), - DecodeError::UnknownRequiredFeature => f.write_str("Unknown required feature preventing decode"), - DecodeError::InvalidValue => f.write_str("Nonsense bytes didn't map to the type they were interpreted as"), + DecodeError::UnknownRequiredFeature => { + f.write_str("Unknown required feature preventing decode") + }, + DecodeError::InvalidValue => { + f.write_str("Nonsense bytes didn't map to the type they were interpreted as") + }, DecodeError::ShortRead => f.write_str("Packet extended beyond the provided bytes"), - DecodeError::BadLengthDescriptor => f.write_str("A length descriptor in the packet didn't describe the later data correctly"), + DecodeError::BadLengthDescriptor => f.write_str( + "A length descriptor in the packet didn't describe the later data correctly", + ), DecodeError::Io(ref e) => fmt::Debug::fmt(e, f), - DecodeError::UnsupportedCompression => f.write_str("We don't support receiving messages with zlib-compressed fields"), - DecodeError::DangerousValue => f.write_str("Value would be dangerous to continue execution with"), + DecodeError::UnsupportedCompression => { + f.write_str("We don't support receiving messages with zlib-compressed fields") + }, + DecodeError::DangerousValue => { + f.write_str("Value would be dangerous to continue execution with") + }, } } } @@ -2773,7 +2810,9 @@ impl_writeable_msg!(ChannelReady, { (1, short_channel_id_alias, option), }); -pub(crate) fn write_features_up_to_13(w: &mut W, le_flags: &[u8]) -> Result<(), io::Error> { +pub(crate) fn write_features_up_to_13( + w: &mut W, le_flags: &[u8], +) -> Result<(), io::Error> { let len = core::cmp::min(2, le_flags.len()); (len as u16).write(w)?; for i in (0..len).rev() { @@ -3039,13 +3078,9 @@ impl_writeable_msg!(UpdateFulfillHTLC, { payment_preimage }, {}); -impl_writeable_msg!(PeerStorage, { - data -}, {}); +impl_writeable_msg!(PeerStorage, { data }, {}); -impl_writeable_msg!(PeerStorageRetrieval, { - data -}, {}); +impl_writeable_msg!(PeerStorageRetrieval, { data }, {}); // Note that this is written as a part of ChannelManager objects, and thus cannot change its // serialization format in a way which assumes we know the total serialized length/message end @@ -3055,7 +3090,7 @@ impl Writeable for OnionPacket { self.version.write(w)?; match self.public_key { Ok(pubkey) => pubkey.write(w)?, - Err(_) => [0u8;33].write(w)?, + Err(_) => [0u8; 33].write(w)?, } w.write_all(&self.hop_data)?; self.hmac.write(w)?; @@ -3068,7 +3103,7 @@ impl Readable for OnionPacket { Ok(OnionPacket { version: Readable::read(r)?, public_key: { - let mut buf = [0u8;33]; + let mut buf = [0u8; 33]; r.read_exact(&mut buf)?; PublicKey::from_slice(&buf) }, @@ -3096,11 +3131,10 @@ impl LengthReadable for OnionMessage { let len: u16 = Readable::read(r)?; let mut packet_reader = FixedLengthReader::new(r, len as u64); let onion_routing_packet: onion_message::packet::Packet = - ::read_from_fixed_length_buffer(&mut packet_reader)?; - Ok(Self { - blinding_point, - onion_routing_packet, - }) + ::read_from_fixed_length_buffer( + &mut packet_reader, + )?; + Ok(Self { blinding_point, onion_routing_packet }) } } @@ -3140,8 +3174,10 @@ impl<'a> Writeable for OutboundOnionPayload<'a> { }); }, Self::TrampolineEntrypoint { - amt_to_forward, outgoing_cltv_value, ref multipath_trampoline_data, - ref trampoline_packet + amt_to_forward, + outgoing_cltv_value, + ref multipath_trampoline_data, + ref trampoline_packet, } => { _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*amt_to_forward), required), @@ -3151,8 +3187,11 @@ impl<'a> Writeable for OutboundOnionPayload<'a> { }); }, Self::BlindedTrampolineEntrypoint { - amt_to_forward, outgoing_cltv_value, current_path_key, - ref multipath_trampoline_data, ref trampoline_packet + amt_to_forward, + outgoing_cltv_value, + current_path_key, + ref multipath_trampoline_data, + ref trampoline_packet, } => { _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*amt_to_forward), required), @@ -3163,14 +3202,19 @@ impl<'a> Writeable for OutboundOnionPayload<'a> { }); }, Self::Receive { - ref payment_data, ref payment_metadata, ref keysend_preimage, sender_intended_htlc_amt_msat, - cltv_expiry_height, ref custom_tlvs, + ref payment_data, + ref payment_metadata, + ref keysend_preimage, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + ref custom_tlvs, } => { // We need to update [`ln::outbound_payment::RecipientOnionFields::with_custom_tlvs`] // to reject any reserved types in the experimental range if new ones are ever // standardized. let keysend_tlv = keysend_preimage.map(|preimage| (5482373484, preimage.encode())); - let mut custom_tlvs: Vec<&(u64, Vec)> = custom_tlvs.iter().chain(keysend_tlv.iter()).collect(); + let mut custom_tlvs: Vec<&(u64, Vec)> = + custom_tlvs.iter().chain(keysend_tlv.iter()).collect(); custom_tlvs.sort_unstable_by_key(|(typ, _)| *typ); _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required), @@ -3186,15 +3230,22 @@ impl<'a> Writeable for OutboundOnionPayload<'a> { }); }, Self::BlindedReceive { - sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs, - intro_node_blinding_point, keysend_preimage, ref invoice_request, ref custom_tlvs, + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + encrypted_tlvs, + intro_node_blinding_point, + keysend_preimage, + ref invoice_request, + ref custom_tlvs, } => { // We need to update [`ln::outbound_payment::RecipientOnionFields::with_custom_tlvs`] // to reject any reserved types in the experimental range if new ones are ever // standardized. let invoice_request_tlv = invoice_request.map(|invreq| (77_777, invreq.encode())); // TODO: update TLV type once the async payments spec is merged let keysend_tlv = keysend_preimage.map(|preimage| (5482373484, preimage.encode())); - let mut custom_tlvs: Vec<&(u64, Vec)> = custom_tlvs.iter() + let mut custom_tlvs: Vec<&(u64, Vec)> = custom_tlvs + .iter() .chain(invoice_request_tlv.iter()) .chain(keysend_tlv.iter()) .collect(); @@ -3224,7 +3275,9 @@ impl<'a> Writeable for OutboundTrampolinePayload<'a> { }, #[cfg(test)] Self::Receive { - ref payment_data, sender_intended_htlc_amt_msat, cltv_expiry_height, + ref payment_data, + sender_intended_htlc_amt_msat, + cltv_expiry_height, } => { _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required), @@ -3232,7 +3285,12 @@ impl<'a> Writeable for OutboundTrampolinePayload<'a> { (8, payment_data, option) }); }, - Self::LegacyBlindedPathEntry { amt_to_forward, outgoing_cltv_value, payment_paths, invoice_features } => { + Self::LegacyBlindedPathEntry { + amt_to_forward, + outgoing_cltv_value, + payment_paths, + invoice_features, + } => { let mut blinded_path_serialization = [0u8; 2048]; // Fixed-length buffer on the stack let serialization_length = { let buffer_size = blinded_path_serialization.len(); @@ -3243,7 +3301,8 @@ impl<'a> Writeable for OutboundTrampolinePayload<'a> { } buffer_size - blinded_path_slice.len() }; - let blinded_path_serialization = &blinded_path_serialization[..serialization_length]; + let blinded_path_serialization = + &blinded_path_serialization[..serialization_length]; _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*amt_to_forward), required), (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required), @@ -3251,13 +3310,21 @@ impl<'a> Writeable for OutboundTrampolinePayload<'a> { (22, WithoutLength(blinded_path_serialization), required) }); }, - Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point} => { + Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point } => { _encode_varint_length_prefixed_tlv!(w, { (10, *encrypted_tlvs, required_vec), (12, intro_node_blinding_point, option) }); }, - Self::BlindedReceive { sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs, intro_node_blinding_point, keysend_preimage, custom_tlvs } => { + Self::BlindedReceive { + sender_intended_htlc_amt_msat, + total_msat, + cltv_expiry_height, + encrypted_tlvs, + intro_node_blinding_point, + keysend_preimage, + custom_tlvs, + } => { _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required), (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required), @@ -3266,14 +3333,16 @@ impl<'a> Writeable for OutboundTrampolinePayload<'a> { (18, HighZeroBytesDroppedBigSize(*total_msat), required), (20, keysend_preimage, option) }, custom_tlvs.iter()); - } + }, } Ok(()) } } - -impl ReadableArgs<(Option, NS)> for InboundOnionPayload where NS::Target: NodeSigner { +impl ReadableArgs<(Option, NS)> for InboundOnionPayload +where + NS::Target: NodeSigner, +{ fn read(r: &mut R, args: (Option, NS)) -> Result { let (update_add_blinding_point, node_signer) = args; @@ -3314,42 +3383,54 @@ impl ReadableArgs<(Option, NS)> for InboundOnionPayload wh Ok(true) }); - if amt.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) } + if amt.unwrap_or(0) > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } if intro_node_blinding_point.is_some() && update_add_blinding_point.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } if let Some(trampoline_onion_packet) = trampoline_onion_packet { - if payment_metadata.is_some() || encrypted_tlvs_opt.is_some() || - total_msat.is_some() - { return Err(DecodeError::InvalidValue) } + if payment_metadata.is_some() || encrypted_tlvs_opt.is_some() || total_msat.is_some() { + return Err(DecodeError::InvalidValue); + } return Ok(Self::TrampolineEntrypoint(InboundTrampolineEntrypointPayload { amt_to_forward: amt.ok_or(DecodeError::InvalidValue)?, outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?, multipath_trampoline_data: payment_data, trampoline_packet: trampoline_onion_packet, current_path_key: intro_node_blinding_point, - })) + })); } if let Some(blinding_point) = intro_node_blinding_point.or(update_add_blinding_point) { if short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } let enc_tlvs = encrypted_tlvs_opt.ok_or(DecodeError::InvalidValue)?.0; - let enc_tlvs_ss = node_signer.ecdh(Recipient::Node, &blinding_point, None) + let enc_tlvs_ss = node_signer + .ecdh(Recipient::Node, &blinding_point, None) .map_err(|_| DecodeError::InvalidValue)?; let rho = onion_utils::gen_rho_from_shared_secret(&enc_tlvs_ss.secret_bytes()); let mut s = Cursor::new(&enc_tlvs); let mut reader = FixedLengthReader::new(&mut s, enc_tlvs.len() as u64); match ChaChaPolyReadAdapter::read(&mut reader, rho)? { - ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Forward(ForwardTlvs { - short_channel_id, payment_relay, payment_constraints, features, next_blinding_override - })} => { - if amt.is_some() || cltv_value.is_some() || total_msat.is_some() || - keysend_preimage.is_some() || invoice_request.is_some() + ChaChaPolyReadAdapter { + readable: + BlindedPaymentTlvs::Forward(ForwardTlvs { + short_channel_id, + payment_relay, + payment_constraints, + features, + next_blinding_override, + }), + } => { + if amt.is_some() + || cltv_value.is_some() || total_msat.is_some() + || keysend_preimage.is_some() + || invoice_request.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } Ok(Self::BlindedForward(InboundOnionBlindedForwardPayload { short_channel_id, @@ -3368,9 +3449,13 @@ impl ReadableArgs<(Option, NS)> for InboundOnionPayload wh } let UnauthenticatedReceiveTlvs { - payment_secret, payment_constraints, payment_context, + payment_secret, + payment_constraints, + payment_context, } = tlvs; - if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) } + if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } Ok(Self::BlindedReceive(InboundOnionBlindedReceivePayload { sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?, total_msat: total_msat.ok_or(DecodeError::InvalidValue)?, @@ -3386,9 +3471,14 @@ impl ReadableArgs<(Option, NS)> for InboundOnionPayload wh }, } } else if let Some(short_channel_id) = short_id { - if payment_data.is_some() || payment_metadata.is_some() || encrypted_tlvs_opt.is_some() || - total_msat.is_some() || invoice_request.is_some() - { return Err(DecodeError::InvalidValue) } + if payment_data.is_some() + || payment_metadata.is_some() + || encrypted_tlvs_opt.is_some() + || total_msat.is_some() + || invoice_request.is_some() + { + return Err(DecodeError::InvalidValue); + } Ok(Self::Forward(InboundOnionForwardPayload { short_channel_id, amt_to_forward: amt.ok_or(DecodeError::InvalidValue)?, @@ -3396,7 +3486,7 @@ impl ReadableArgs<(Option, NS)> for InboundOnionPayload wh })) } else { if encrypted_tlvs_opt.is_some() || total_msat.is_some() || invoice_request.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } if let Some(data) = &payment_data { if data.total_msat > MAX_VALUE_MSAT { @@ -3415,7 +3505,10 @@ impl ReadableArgs<(Option, NS)> for InboundOnionPayload wh } } -impl ReadableArgs<(Option, NS)> for InboundTrampolinePayload where NS::Target: NodeSigner { +impl ReadableArgs<(Option, NS)> for InboundTrampolinePayload +where + NS::Target: NodeSigner, +{ fn read(r: &mut R, args: (Option, NS)) -> Result { let (update_add_blinding_point, node_signer) = args; @@ -3453,29 +3546,41 @@ impl ReadableArgs<(Option, NS)> for InboundTrampolinePaylo Ok(true) }); - if amt.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) } + if amt.unwrap_or(0) > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } if intro_node_blinding_point.is_some() && update_add_blinding_point.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } if let Some(blinding_point) = intro_node_blinding_point.or(update_add_blinding_point) { if next_trampoline.is_some() || payment_data.is_some() || payment_metadata.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } let enc_tlvs = encrypted_tlvs_opt.ok_or(DecodeError::InvalidValue)?.0; - let enc_tlvs_ss = node_signer.ecdh(Recipient::Node, &blinding_point, None) + let enc_tlvs_ss = node_signer + .ecdh(Recipient::Node, &blinding_point, None) .map_err(|_| DecodeError::InvalidValue)?; let rho = onion_utils::gen_rho_from_shared_secret(&enc_tlvs_ss.secret_bytes()); let mut s = Cursor::new(&enc_tlvs); let mut reader = FixedLengthReader::new(&mut s, enc_tlvs.len() as u64); match ChaChaPolyReadAdapter::read(&mut reader, rho)? { - ChaChaPolyReadAdapter { readable: BlindedTrampolineTlvs::Forward(TrampolineForwardTlvs { - next_trampoline, payment_relay, payment_constraints, features, next_blinding_override - })} => { - if amt.is_some() || cltv_value.is_some() || total_msat.is_some() || - keysend_preimage.is_some() || invoice_request.is_some() + ChaChaPolyReadAdapter { + readable: + BlindedTrampolineTlvs::Forward(TrampolineForwardTlvs { + next_trampoline, + payment_relay, + payment_constraints, + features, + next_blinding_override, + }), + } => { + if amt.is_some() + || cltv_value.is_some() || total_msat.is_some() + || keysend_preimage.is_some() + || invoice_request.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } Ok(Self::BlindedForward(InboundTrampolineBlindedForwardPayload { next_trampoline, @@ -3486,7 +3591,9 @@ impl ReadableArgs<(Option, NS)> for InboundTrampolinePaylo next_blinding_override, })) }, - ChaChaPolyReadAdapter { readable: BlindedTrampolineTlvs::Receive(receive_tlvs) } => { + ChaChaPolyReadAdapter { + readable: BlindedTrampolineTlvs::Receive(receive_tlvs), + } => { let ReceiveTlvs { tlvs, authentication: (hmac, nonce) } = receive_tlvs; let expanded_key = node_signer.get_inbound_payment_key(); if tlvs.verify_for_offer_payment(hmac, nonce, &expanded_key).is_err() { @@ -3494,9 +3601,13 @@ impl ReadableArgs<(Option, NS)> for InboundTrampolinePaylo } let UnauthenticatedReceiveTlvs { - payment_secret, payment_constraints, payment_context, + payment_secret, + payment_constraints, + payment_context, } = tlvs; - if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) } + if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { + return Err(DecodeError::InvalidValue); + } Ok(Self::BlindedReceive(InboundOnionBlindedReceivePayload { sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?, total_msat: total_msat.ok_or(DecodeError::InvalidValue)?, @@ -3512,9 +3623,14 @@ impl ReadableArgs<(Option, NS)> for InboundTrampolinePaylo }, } } else if let Some(next_trampoline) = next_trampoline { - if payment_data.is_some() || payment_metadata.is_some() || encrypted_tlvs_opt.is_some() || - total_msat.is_some() || invoice_request.is_some() - { return Err(DecodeError::InvalidValue) } + if payment_data.is_some() + || payment_metadata.is_some() + || encrypted_tlvs_opt.is_some() + || total_msat.is_some() + || invoice_request.is_some() + { + return Err(DecodeError::InvalidValue); + } Ok(Self::Forward(InboundTrampolineForwardPayload { next_trampoline, amt_to_forward: amt.ok_or(DecodeError::InvalidValue)?, @@ -3522,7 +3638,7 @@ impl ReadableArgs<(Option, NS)> for InboundTrampolinePaylo })) } else { if encrypted_tlvs_opt.is_some() || total_msat.is_some() || invoice_request.is_some() { - return Err(DecodeError::InvalidValue) + return Err(DecodeError::InvalidValue); } if let Some(data) = &payment_data { if data.total_msat > MAX_VALUE_MSAT { @@ -3541,7 +3657,6 @@ impl ReadableArgs<(Option, NS)> for InboundTrampolinePaylo } } - impl Writeable for Ping { fn write(&self, w: &mut W) -> Result<(), io::Error> { self.ponglen.write(w)?; @@ -3558,7 +3673,7 @@ impl LengthReadable for Ping { let byteslen = Readable::read(r)?; r.read_exact(&mut vec![0u8; byteslen as usize][..])?; byteslen - } + }, }) } } @@ -3577,7 +3692,7 @@ impl LengthReadable for Pong { let byteslen = Readable::read(r)?; r.read_exact(&mut vec![0u8; byteslen as usize][..])?; byteslen - } + }, }) } } @@ -3717,7 +3832,7 @@ impl LengthReadable for ErrorMessage { Ok(s) => s, Err(_) => return Err(DecodeError::InvalidValue), } - } + }, }) } } @@ -3744,7 +3859,7 @@ impl LengthReadable for WarningMessage { Ok(s) => s, Err(_) => return Err(DecodeError::InvalidValue), } - } + }, }) } } @@ -3786,7 +3901,9 @@ impl LengthReadable for UnsignedNodeAnnouncement { let mut excess = false; let mut excess_byte = 0; loop { - if addr_len <= addr_readpos { break; } + if addr_len <= addr_readpos { + break; + } match Readable::read(r) { Ok(Ok(addr)) => { if addr_len < addr_readpos + 1 + addr.len() { @@ -3871,16 +3988,13 @@ impl LengthReadable for QueryShortChannelIds { // Read short_channel_ids (8-bytes each), for the u16 encoding_len // less the 1-byte encoding_type - let short_channel_id_count: u16 = (encoding_len - 1)/8; + let short_channel_id_count: u16 = (encoding_len - 1) / 8; let mut short_channel_ids = Vec::with_capacity(short_channel_id_count as usize); for _ in 0..short_channel_id_count { short_channel_ids.push(Readable::read(r)?); } - Ok(QueryShortChannelIds { - chain_hash, - short_channel_ids, - }) + Ok(QueryShortChannelIds { chain_hash, short_channel_ids }) } } @@ -3950,7 +4064,7 @@ impl LengthReadable for ReplyChannelRange { // Read short_channel_ids (8-bytes each), for the u16 encoding_len // less the 1-byte encoding_type - let short_channel_id_count: u16 = (encoding_len - 1)/8; + let short_channel_id_count: u16 = (encoding_len - 1) / 8; let mut short_channel_ids = Vec::with_capacity(short_channel_id_count as usize); for _ in 0..short_channel_id_count { short_channel_ids.push(Readable::read(r)?); @@ -3961,7 +4075,7 @@ impl LengthReadable for ReplyChannelRange { first_blocknum, number_of_blocks, sync_complete, - short_channel_ids + short_channel_ids, }) } } @@ -3992,55 +4106,76 @@ impl_writeable_msg!(GossipTimestampFilter, { #[cfg(test)] mod tests { - use bitcoin::{Amount, Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut}; - use bitcoin::hex::DisplayHex; + use crate::ln::msgs::SocketAddress; + use crate::ln::msgs::{ + self, CommonAcceptChannelFields, CommonOpenChannelFields, FinalOnionHopData, + InboundOnionForwardPayload, InboundOnionReceivePayload, OutboundTrampolinePayload, + TrampolineOnionPacket, + }; use crate::ln::onion_utils::{AttributionData, HMAC_COUNT, HMAC_LEN, HOLD_TIME_LEN, MAX_HOPS}; use crate::ln::types::ChannelId; - use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret}; - use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; - use crate::ln::msgs::{self, FinalOnionHopData, CommonOpenChannelFields, CommonAcceptChannelFields, OutboundTrampolinePayload, TrampolineOnionPacket, InboundOnionForwardPayload, InboundOnionReceivePayload}; - use crate::ln::msgs::SocketAddress; use crate::routing::gossip::{NodeAlias, NodeId}; - use crate::util::ser::{BigSize, Hostname, LengthReadable, Readable, ReadableArgs, TransactionU16LenLimited, Writeable}; + use crate::types::features::{ + ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures, + }; + use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; + use crate::util::ser::{ + BigSize, Hostname, LengthReadable, Readable, ReadableArgs, TransactionU16LenLimited, + Writeable, + }; use crate::util::test_utils; + use bitcoin::hex::DisplayHex; + use bitcoin::{Amount, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Witness}; - use bitcoin::hex::FromHex; use bitcoin::address::Address; - use bitcoin::network::Network; use bitcoin::constants::ChainHash; - use bitcoin::script::Builder; - use bitcoin::opcodes; use bitcoin::hash_types::Txid; + use bitcoin::hex::FromHex; use bitcoin::locktime::absolute::LockTime; + use bitcoin::network::Network; + use bitcoin::opcodes; + use bitcoin::script::Builder; use bitcoin::transaction::Version; - use bitcoin::secp256k1::{PublicKey,SecretKey}; - use bitcoin::secp256k1::{Secp256k1, Message}; + use bitcoin::secp256k1::{Message, Secp256k1}; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + use crate::chain::transaction::OutPoint; use crate::io::{self, Cursor}; use crate::prelude::*; use core::str::FromStr; - use crate::chain::transaction::OutPoint; - #[cfg(feature = "std")] - use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; - use types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath}; #[cfg(feature = "std")] use crate::ln::msgs::SocketAddressParseError; + #[cfg(feature = "std")] + use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; + use types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; #[test] fn encoding_channel_reestablish() { let public_key = { let secp_ctx = Secp256k1::new(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()) + PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap()[..], + ) + .unwrap(), + ) }; let cr = msgs::ChannelReestablish { - channel_id: ChannelId::from_bytes([4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0]), + channel_id: ChannelId::from_bytes([ + 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, + ]), next_local_commitment_number: 3, next_remote_commitment_number: 4, - your_last_per_commitment_secret: [9;32], + your_last_per_commitment_secret: [9; 32], my_current_per_commitment_point: public_key, next_funding_txid: None, }; @@ -4049,11 +4184,15 @@ mod tests { assert_eq!( encoded_value, vec![ - 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, // channel_id + 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, // channel_id 0, 0, 0, 0, 0, 0, 0, 3, // next_local_commitment_number 0, 0, 0, 0, 0, 0, 0, 4, // next_remote_commitment_number - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // your_last_per_commitment_secret - 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143, // my_current_per_commitment_point + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, // your_last_per_commitment_secret + 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, + 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, + 143, // my_current_per_commitment_point ] ); } @@ -4062,63 +4201,88 @@ mod tests { fn encoding_channel_reestablish_with_next_funding_txid() { let public_key = { let secp_ctx = Secp256k1::new(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&>::from_hex("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()) + PublicKey::from_secret_key( + &secp_ctx, + &SecretKey::from_slice( + &>::from_hex( + "0101010101010101010101010101010101010101010101010101010101010101", + ) + .unwrap()[..], + ) + .unwrap(), + ) }; let cr = msgs::ChannelReestablish { - channel_id: ChannelId::from_bytes([4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0]), + channel_id: ChannelId::from_bytes([ + 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, + ]), next_local_commitment_number: 3, next_remote_commitment_number: 4, - your_last_per_commitment_secret: [9;32], + your_last_per_commitment_secret: [9; 32], my_current_per_commitment_point: public_key, - next_funding_txid: Some(Txid::from_raw_hash(bitcoin::hashes::Hash::from_slice(&[ - 48, 167, 250, 69, 152, 48, 103, 172, 164, 99, 59, 19, 23, 11, 92, 84, 15, 80, 4, 12, 98, 82, 75, 31, 201, 11, 91, 23, 98, 23, 53, 124, - ]).unwrap())), + next_funding_txid: Some(Txid::from_raw_hash( + bitcoin::hashes::Hash::from_slice(&[ + 48, 167, 250, 69, 152, 48, 103, 172, 164, 99, 59, 19, 23, 11, 92, 84, 15, 80, + 4, 12, 98, 82, 75, 31, 201, 11, 91, 23, 98, 23, 53, 124, + ]) + .unwrap(), + )), }; let encoded_value = cr.encode(); assert_eq!( encoded_value, vec![ - 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, // channel_id + 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, // channel_id 0, 0, 0, 0, 0, 0, 0, 3, // next_local_commitment_number 0, 0, 0, 0, 0, 0, 0, 4, // next_remote_commitment_number - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // your_last_per_commitment_secret - 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143, // my_current_per_commitment_point - 0, // Type (next_funding_txid) - 32, // Length - 48, 167, 250, 69, 152, 48, 103, 172, 164, 99, 59, 19, 23, 11, 92, 84, 15, 80, 4, 12, 98, 82, 75, 31, 201, 11, 91, 23, 98, 23, 53, 124, // Value + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, // your_last_per_commitment_secret + 3, 27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, + 24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, + 143, // my_current_per_commitment_point + 0, // Type (next_funding_txid) + 32, // Length + 48, 167, 250, 69, 152, 48, 103, 172, 164, 99, 59, 19, 23, 11, 92, 84, 15, 80, 4, + 12, 98, 82, 75, 31, 201, 11, 91, 23, 98, 23, 53, 124, // Value ] ); } macro_rules! get_keys_from { - ($slice: expr, $secp_ctx: expr) => { - { - let privkey = SecretKey::from_slice(&>::from_hex($slice).unwrap()[..]).unwrap(); - let pubkey = PublicKey::from_secret_key(&$secp_ctx, &privkey); - (privkey, pubkey) - } - } + ($slice: expr, $secp_ctx: expr) => {{ + let privkey = SecretKey::from_slice(&>::from_hex($slice).unwrap()[..]).unwrap(); + let pubkey = PublicKey::from_secret_key(&$secp_ctx, &privkey); + (privkey, pubkey) + }}; } macro_rules! get_sig_on { - ($privkey: expr, $ctx: expr, $string: expr) => { - { - let sighash = Message::from_digest_slice(&$string.into_bytes()[..]).unwrap(); - $ctx.sign_ecdsa(&sighash, &$privkey) - } - } + ($privkey: expr, $ctx: expr, $string: expr) => {{ + let sighash = Message::from_digest_slice(&$string.into_bytes()[..]).unwrap(); + $ctx.sign_ecdsa(&sighash, &$privkey) + }}; } #[test] fn encoding_announcement_signatures() { let secp_ctx = Secp256k1::new(); - let (privkey, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_2 = get_sig_on!(privkey, secp_ctx, String::from("02020202020202020202020202020202")); + let (privkey, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_2 = + get_sig_on!(privkey, secp_ctx, String::from("02020202020202020202020202020202")); let announcement_signatures = msgs::AnnouncementSignatures { - channel_id: ChannelId::from_bytes([4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0]), + channel_id: ChannelId::from_bytes([ + 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, + ]), short_channel_id: 2316138423780173, node_signature: sig_1, bitcoin_signature: sig_2, @@ -4130,14 +4294,30 @@ mod tests { fn do_encoding_channel_announcement(unknown_features_bits: bool, excess_data: bool) { let secp_ctx = Secp256k1::new(); - let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let (privkey_2, pubkey_2) = get_keys_from!("0202020202020202020202020202020202020202020202020202020202020202", secp_ctx); - let (privkey_3, pubkey_3) = get_keys_from!("0303030303030303030303030303030303030303030303030303030303030303", secp_ctx); - let (privkey_4, pubkey_4) = get_keys_from!("0404040404040404040404040404040404040404040404040404040404040404", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_2 = get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_3 = get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_4 = get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let (privkey_2, pubkey_2) = get_keys_from!( + "0202020202020202020202020202020202020202020202020202020202020202", + secp_ctx + ); + let (privkey_3, pubkey_3) = get_keys_from!( + "0303030303030303030303030303030303030303030303030303030303030303", + secp_ctx + ); + let (privkey_4, pubkey_4) = get_keys_from!( + "0404040404040404040404040404040404040404040404040404040404040404", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_2 = + get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_3 = + get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_4 = + get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101")); let mut features = ChannelFeatures::empty(); if unknown_features_bits { features = ChannelFeatures::from_le_bytes(vec![0xFF, 0xFF]); @@ -4150,7 +4330,11 @@ mod tests { node_id_2: NodeId::from_pubkey(&pubkey_2), bitcoin_key_1: NodeId::from_pubkey(&pubkey_3), bitcoin_key_2: NodeId::from_pubkey(&pubkey_4), - excess_data: if excess_data { vec![10, 0, 0, 20, 0, 0, 30, 0, 0, 40] } else { Vec::new() }, + excess_data: if excess_data { + vec![10, 0, 0, 20, 0, 0, 30, 0, 0, 40] + } else { + Vec::new() + }, }; let channel_announcement = msgs::ChannelAnnouncement { node_signature_1: sig_1, @@ -4166,7 +4350,12 @@ mod tests { } else { target_value.append(&mut >::from_hex("0000").unwrap()); } - target_value.append(&mut >::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); + target_value.append( + &mut >::from_hex( + "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + ) + .unwrap(), + ); target_value.append(&mut >::from_hex("00083a840000034d031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b").unwrap()); if excess_data { target_value.append(&mut >::from_hex("0a00001400001e000028").unwrap()); @@ -4182,10 +4371,17 @@ mod tests { do_encoding_channel_announcement(true, true); } - fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, hostname: bool, excess_address_data: bool, excess_data: bool) { + fn do_encoding_node_announcement( + unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, + hostname: bool, excess_address_data: bool, excess_data: bool, + ) { let secp_ctx = Secp256k1::new(); - let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); let features = if unknown_features_bits { NodeFeatures::from_le_bytes(vec![0xFF, 0xFF]) } else { @@ -4194,28 +4390,30 @@ mod tests { }; let mut addresses = Vec::new(); if ipv4 { - addresses.push(SocketAddress::TcpIpV4 { - addr: [255, 254, 253, 252], - port: 9735 - }); + addresses.push(SocketAddress::TcpIpV4 { addr: [255, 254, 253, 252], port: 9735 }); } if ipv6 { addresses.push(SocketAddress::TcpIpV6 { - addr: [255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240], - port: 9735 + addr: [ + 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, + ], + port: 9735, }); } if onionv2 { - addresses.push(msgs::SocketAddress::OnionV2( - [255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 38, 7] - )); + addresses.push(msgs::SocketAddress::OnionV2([ + 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 38, 7, + ])); } if onionv3 { addresses.push(msgs::SocketAddress::OnionV3 { - ed25519_pubkey: [255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224], + ed25519_pubkey: [ + 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, + 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, + ], checksum: 32, version: 16, - port: 9735 + port: 9735, }); } if hostname { @@ -4233,16 +4431,32 @@ mod tests { timestamp: 20190119, node_id: NodeId::from_pubkey(&pubkey_1), rgb: [32; 3], - alias: NodeAlias([16;32]), + alias: NodeAlias([16; 32]), addresses, - excess_address_data: if excess_address_data { vec![33, 108, 40, 11, 83, 149, 162, 84, 110, 126, 75, 38, 99, 224, 79, 129, 22, 34, 241, 90, 79, 146, 232, 58, 162, 233, 43, 162, 165, 115, 193, 57, 20, 44, 84, 174, 99, 7, 42, 30, 193, 238, 125, 192, 192, 75, 222, 92, 132, 120, 6, 23, 42, 160, 92, 146, 194, 42, 232, 227, 8, 209, 210, 105] } else { Vec::new() }, - excess_data: if excess_data { vec![59, 18, 204, 25, 92, 224, 162, 209, 189, 166, 168, 139, 239, 161, 159, 160, 127, 81, 202, 167, 92, 232, 56, 55, 242, 137, 101, 96, 11, 138, 172, 171, 8, 85, 255, 176, 231, 65, 236, 95, 124, 65, 66, 30, 152, 41, 169, 212, 134, 17, 200, 200, 49, 247, 27, 229, 234, 115, 230, 101, 148, 151, 127, 253] } else { Vec::new() }, + excess_address_data: if excess_address_data { + vec![ + 33, 108, 40, 11, 83, 149, 162, 84, 110, 126, 75, 38, 99, 224, 79, 129, 22, 34, + 241, 90, 79, 146, 232, 58, 162, 233, 43, 162, 165, 115, 193, 57, 20, 44, 84, + 174, 99, 7, 42, 30, 193, 238, 125, 192, 192, 75, 222, 92, 132, 120, 6, 23, 42, + 160, 92, 146, 194, 42, 232, 227, 8, 209, 210, 105, + ] + } else { + Vec::new() + }, + excess_data: if excess_data { + vec![ + 59, 18, 204, 25, 92, 224, 162, 209, 189, 166, 168, 139, 239, 161, 159, 160, + 127, 81, 202, 167, 92, 232, 56, 55, 242, 137, 101, 96, 11, 138, 172, 171, 8, + 85, 255, 176, 231, 65, 236, 95, 124, 65, 66, 30, 152, 41, 169, 212, 134, 17, + 200, 200, 49, 247, 27, 229, 234, 115, 230, 101, 148, 151, 127, 253, + ] + } else { + Vec::new() + }, }; addr_len += unsigned_node_announcement.excess_address_data.len() as u16; - let node_announcement = msgs::NodeAnnouncement { - signature: sig_1, - contents: unsigned_node_announcement, - }; + let node_announcement = + msgs::NodeAnnouncement { signature: sig_1, contents: unsigned_node_announcement }; let encoded_value = node_announcement.encode(); let mut target_value = >::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap(); if unknown_features_bits { @@ -4256,13 +4470,20 @@ mod tests { target_value.append(&mut >::from_hex("01fffefdfc2607").unwrap()); } if ipv6 { - target_value.append(&mut >::from_hex("02fffefdfcfbfaf9f8f7f6f5f4f3f2f1f02607").unwrap()); + target_value.append( + &mut >::from_hex("02fffefdfcfbfaf9f8f7f6f5f4f3f2f1f02607").unwrap(), + ); } if onionv2 { target_value.append(&mut >::from_hex("03fffefdfcfbfaf9f8f7f62607").unwrap()); } if onionv3 { - target_value.append(&mut >::from_hex("04fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e00020102607").unwrap()); + target_value.append( + &mut >::from_hex( + "04fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e00020102607", + ) + .unwrap(), + ); } if hostname { target_value.append(&mut >::from_hex("0504686f73742607").unwrap()); @@ -4292,8 +4513,12 @@ mod tests { fn do_encoding_channel_update(direction: bool, disable: bool, excess_data: bool) { let secp_ctx = Secp256k1::new(); - let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); let unsigned_channel_update = msgs::UnsignedChannelUpdate { chain_hash: ChainHash::using_genesis_block(Network::Bitcoin), short_channel_id: 2316138423780173, @@ -4305,15 +4530,18 @@ mod tests { htlc_maximum_msat: 131355275467161, fee_base_msat: 10000, fee_proportional_millionths: 20, - excess_data: if excess_data { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() } - }; - let channel_update = msgs::ChannelUpdate { - signature: sig_1, - contents: unsigned_channel_update + excess_data: if excess_data { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }, }; + let channel_update = + msgs::ChannelUpdate { signature: sig_1, contents: unsigned_channel_update }; let encoded_value = channel_update.encode(); let mut target_value = >::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap(); - target_value.append(&mut >::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); + target_value.append( + &mut >::from_hex( + "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + ) + .unwrap(), + ); target_value.append(&mut >::from_hex("00083a840000034d013413a7").unwrap()); target_value.append(&mut >::from_hex("01").unwrap()); target_value.append(&mut >::from_hex("00").unwrap()); @@ -4325,7 +4553,8 @@ mod tests { let flag = target_value.last_mut().unwrap(); *flag = *flag | 1 << 1; } - target_value.append(&mut >::from_hex("009000000000000f42400000271000000014").unwrap()); + target_value + .append(&mut >::from_hex("009000000000000f42400000271000000014").unwrap()); target_value.append(&mut >::from_hex("0000777788889999").unwrap()); if excess_data { target_value.append(&mut >::from_hex("000000003b9aca00").unwrap()); @@ -4347,12 +4576,30 @@ mod tests { fn do_encoding_open_channel(random_bit: bool, shutdown: bool, incl_chan_type: bool) { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let (_, pubkey_2) = get_keys_from!("0202020202020202020202020202020202020202020202020202020202020202", secp_ctx); - let (_, pubkey_3) = get_keys_from!("0303030303030303030303030303030303030303030303030303030303030303", secp_ctx); - let (_, pubkey_4) = get_keys_from!("0404040404040404040404040404040404040404040404040404040404040404", secp_ctx); - let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx); - let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let (_, pubkey_2) = get_keys_from!( + "0202020202020202020202020202020202020202020202020202020202020202", + secp_ctx + ); + let (_, pubkey_3) = get_keys_from!( + "0303030303030303030303030303030303030303030303030303030303030303", + secp_ctx + ); + let (_, pubkey_4) = get_keys_from!( + "0404040404040404040404040404040404040404040404040404040404040404", + secp_ctx + ); + let (_, pubkey_5) = get_keys_from!( + "0505050505050505050505050505050505050505050505050505050505050505", + secp_ctx + ); + let (_, pubkey_6) = get_keys_from!( + "0606060606060606060606060606060606060606060606060606060606060606", + secp_ctx + ); let open_channel = msgs::OpenChannel { common_fields: CommonOpenChannelFields { chain_hash: ChainHash::using_genesis_block(Network::Bitcoin), @@ -4371,15 +4618,34 @@ mod tests { htlc_basepoint: pubkey_5, first_per_commitment_point: pubkey_6, channel_flags: if random_bit { 1 << 5 } else { 0 }, - shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None }, - channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None }, + shutdown_scriptpubkey: if shutdown { + Some( + Address::p2pkh( + &::bitcoin::PublicKey { compressed: true, inner: pubkey_1 }, + Network::Testnet, + ) + .script_pubkey(), + ) + } else { + None + }, + channel_type: if incl_chan_type { + Some(ChannelTypeFeatures::empty()) + } else { + None + }, }, push_msat: 2536655962884945560, channel_reserve_satoshis: 8665828695742877976, }; let encoded_value = open_channel.encode(); let mut target_value = Vec::new(); - target_value.append(&mut >::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); + target_value.append( + &mut >::from_hex( + "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + ) + .unwrap(), + ); target_value.append(&mut >::from_hex("02020202020202020202020202020202020202020202020202020202020202021234567890123456233403289122369832144668701144767633030896203198784335490624111800083a840000034d000c89d4c0bcc0bc031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f703f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap()); if random_bit { target_value.append(&mut >::from_hex("20").unwrap()); @@ -4387,7 +4653,10 @@ mod tests { target_value.append(&mut >::from_hex("00").unwrap()); } if shutdown { - target_value.append(&mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap()); + target_value.append( + &mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac") + .unwrap(), + ); } if incl_chan_type { target_value.append(&mut >::from_hex("0100").unwrap()); @@ -4407,15 +4676,38 @@ mod tests { do_encoding_open_channel(true, true, true); } - fn do_encoding_open_channelv2(random_bit: bool, shutdown: bool, incl_chan_type: bool, require_confirmed_inputs: bool) { + fn do_encoding_open_channelv2( + random_bit: bool, shutdown: bool, incl_chan_type: bool, require_confirmed_inputs: bool, + ) { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let (_, pubkey_2) = get_keys_from!("0202020202020202020202020202020202020202020202020202020202020202", secp_ctx); - let (_, pubkey_3) = get_keys_from!("0303030303030303030303030303030303030303030303030303030303030303", secp_ctx); - let (_, pubkey_4) = get_keys_from!("0404040404040404040404040404040404040404040404040404040404040404", secp_ctx); - let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx); - let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx); - let (_, pubkey_7) = get_keys_from!("0707070707070707070707070707070707070707070707070707070707070707", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let (_, pubkey_2) = get_keys_from!( + "0202020202020202020202020202020202020202020202020202020202020202", + secp_ctx + ); + let (_, pubkey_3) = get_keys_from!( + "0303030303030303030303030303030303030303030303030303030303030303", + secp_ctx + ); + let (_, pubkey_4) = get_keys_from!( + "0404040404040404040404040404040404040404040404040404040404040404", + secp_ctx + ); + let (_, pubkey_5) = get_keys_from!( + "0505050505050505050505050505050505050505050505050505050505050505", + secp_ctx + ); + let (_, pubkey_6) = get_keys_from!( + "0606060606060606060606060606060606060606060606060606060606060606", + secp_ctx + ); + let (_, pubkey_7) = get_keys_from!( + "0707070707070707070707070707070707070707070707070707070707070707", + secp_ctx + ); let open_channelv2 = msgs::OpenChannelV2 { common_fields: CommonOpenChannelFields { chain_hash: ChainHash::using_genesis_block(Network::Bitcoin), @@ -4434,8 +4726,22 @@ mod tests { htlc_basepoint: pubkey_5, first_per_commitment_point: pubkey_6, channel_flags: if random_bit { 1 << 5 } else { 0 }, - shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None }, - channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None }, + shutdown_scriptpubkey: if shutdown { + Some( + Address::p2pkh( + &::bitcoin::PublicKey { compressed: true, inner: pubkey_1 }, + Network::Testnet, + ) + .script_pubkey(), + ) + } else { + None + }, + channel_type: if incl_chan_type { + Some(ChannelTypeFeatures::empty()) + } else { + None + }, }, funding_feerate_sat_per_1000_weight: 821716, locktime: 305419896, @@ -4444,8 +4750,18 @@ mod tests { }; let encoded_value = open_channelv2.encode(); let mut target_value = Vec::new(); - target_value.append(&mut >::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); - target_value.append(&mut >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap()); + target_value.append( + &mut >::from_hex( + "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "0202020202020202020202020202020202020202020202020202020202020202", + ) + .unwrap(), + ); target_value.append(&mut >::from_hex("000c89d4").unwrap()); target_value.append(&mut >::from_hex("000c89d4").unwrap()); target_value.append(&mut >::from_hex("1234567890123456").unwrap()); @@ -4455,13 +4771,48 @@ mod tests { target_value.append(&mut >::from_hex("c0bc").unwrap()); target_value.append(&mut >::from_hex("c0bc").unwrap()); target_value.append(&mut >::from_hex("12345678").unwrap()); - target_value.append(&mut >::from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f").unwrap()); - target_value.append(&mut >::from_hex("024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766").unwrap()); - target_value.append(&mut >::from_hex("02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337").unwrap()); - target_value.append(&mut >::from_hex("03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b").unwrap()); - target_value.append(&mut >::from_hex("0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7").unwrap()); - target_value.append(&mut >::from_hex("03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap()); - target_value.append(&mut >::from_hex("02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f").unwrap()); + target_value.append( + &mut >::from_hex( + "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a", + ) + .unwrap(), + ); + target_value.append( + &mut >::from_hex( + "02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f", + ) + .unwrap(), + ); if random_bit { target_value.append(&mut >::from_hex("20").unwrap()); @@ -4469,7 +4820,10 @@ mod tests { target_value.append(&mut >::from_hex("00").unwrap()); } if shutdown { - target_value.append(&mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap()); + target_value.append( + &mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac") + .unwrap(), + ); } if incl_chan_type { target_value.append(&mut >::from_hex("0100").unwrap()); @@ -4502,12 +4856,30 @@ mod tests { fn do_encoding_accept_channel(shutdown: bool) { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let (_, pubkey_2) = get_keys_from!("0202020202020202020202020202020202020202020202020202020202020202", secp_ctx); - let (_, pubkey_3) = get_keys_from!("0303030303030303030303030303030303030303030303030303030303030303", secp_ctx); - let (_, pubkey_4) = get_keys_from!("0404040404040404040404040404040404040404040404040404040404040404", secp_ctx); - let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx); - let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let (_, pubkey_2) = get_keys_from!( + "0202020202020202020202020202020202020202020202020202020202020202", + secp_ctx + ); + let (_, pubkey_3) = get_keys_from!( + "0303030303030303030303030303030303030303030303030303030303030303", + secp_ctx + ); + let (_, pubkey_4) = get_keys_from!( + "0404040404040404040404040404040404040404040404040404040404040404", + secp_ctx + ); + let (_, pubkey_5) = get_keys_from!( + "0505050505050505050505050505050505050505050505050505050505050505", + secp_ctx + ); + let (_, pubkey_6) = get_keys_from!( + "0606060606060606060606060606060606060606060606060606060606060606", + secp_ctx + ); let accept_channel = msgs::AcceptChannel { common_fields: CommonAcceptChannelFields { temporary_channel_id: ChannelId::from_bytes([2; 32]), @@ -4523,7 +4895,17 @@ mod tests { delayed_payment_basepoint: pubkey_4, htlc_basepoint: pubkey_5, first_per_commitment_point: pubkey_6, - shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None }, + shutdown_scriptpubkey: if shutdown { + Some( + Address::p2pkh( + &::bitcoin::PublicKey { compressed: true, inner: pubkey_1 }, + Network::Testnet, + ) + .script_pubkey(), + ) + } else { + None + }, channel_type: None, }, channel_reserve_satoshis: 3608586615801332854, @@ -4533,7 +4915,10 @@ mod tests { let encoded_value = accept_channel.encode(); let mut target_value = >::from_hex("020202020202020202020202020202020202020202020202020202020202020212345678901234562334032891223698321446687011447600083a840000034d000c89d4c0bcc0bc031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f703f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap(); if shutdown { - target_value.append(&mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap()); + target_value.append( + &mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac") + .unwrap(), + ); } assert_eq!(encoded_value, target_value); } @@ -4546,13 +4931,34 @@ mod tests { fn do_encoding_accept_channelv2(shutdown: bool) { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let (_, pubkey_2) = get_keys_from!("0202020202020202020202020202020202020202020202020202020202020202", secp_ctx); - let (_, pubkey_3) = get_keys_from!("0303030303030303030303030303030303030303030303030303030303030303", secp_ctx); - let (_, pubkey_4) = get_keys_from!("0404040404040404040404040404040404040404040404040404040404040404", secp_ctx); - let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx); - let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx); - let (_, pubkey_7) = get_keys_from!("0707070707070707070707070707070707070707070707070707070707070707", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let (_, pubkey_2) = get_keys_from!( + "0202020202020202020202020202020202020202020202020202020202020202", + secp_ctx + ); + let (_, pubkey_3) = get_keys_from!( + "0303030303030303030303030303030303030303030303030303030303030303", + secp_ctx + ); + let (_, pubkey_4) = get_keys_from!( + "0404040404040404040404040404040404040404040404040404040404040404", + secp_ctx + ); + let (_, pubkey_5) = get_keys_from!( + "0505050505050505050505050505050505050505050505050505050505050505", + secp_ctx + ); + let (_, pubkey_6) = get_keys_from!( + "0606060606060606060606060606060606060606060606060606060606060606", + secp_ctx + ); + let (_, pubkey_7) = get_keys_from!( + "0707070707070707070707070707070707070707070707070707070707070707", + secp_ctx + ); let accept_channelv2 = msgs::AcceptChannelV2 { common_fields: CommonAcceptChannelFields { temporary_channel_id: ChannelId::from_bytes([2; 32]), @@ -4568,7 +4974,17 @@ mod tests { delayed_payment_basepoint: pubkey_4, htlc_basepoint: pubkey_5, first_per_commitment_point: pubkey_6, - shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None }, + shutdown_scriptpubkey: if shutdown { + Some( + Address::p2pkh( + &::bitcoin::PublicKey { compressed: true, inner: pubkey_1 }, + Network::Testnet, + ) + .script_pubkey(), + ) + } else { + None + }, channel_type: None, }, funding_satoshis: 1311768467284833366, @@ -4576,7 +4992,9 @@ mod tests { require_confirmed_inputs: None, }; let encoded_value = accept_channelv2.encode(); - let mut target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); // temporary_channel_id + let mut target_value = + >::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); // temporary_channel_id target_value.append(&mut >::from_hex("1234567890123456").unwrap()); // funding_satoshis target_value.append(&mut >::from_hex("1234567890123456").unwrap()); // dust_limit_satoshis target_value.append(&mut >::from_hex("2334032891223698").unwrap()); // max_htlc_value_in_flight_msat @@ -4584,15 +5002,53 @@ mod tests { target_value.append(&mut >::from_hex("000c89d4").unwrap()); // minimum_depth target_value.append(&mut >::from_hex("c0bc").unwrap()); // to_self_delay target_value.append(&mut >::from_hex("c0bc").unwrap()); // max_accepted_htlcs - target_value.append(&mut >::from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f").unwrap()); // funding_pubkey - target_value.append(&mut >::from_hex("024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766").unwrap()); // revocation_basepoint - target_value.append(&mut >::from_hex("02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337").unwrap()); // payment_basepoint - target_value.append(&mut >::from_hex("03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b").unwrap()); // delayed_payment_basepoint - target_value.append(&mut >::from_hex("0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7").unwrap()); // htlc_basepoint - target_value.append(&mut >::from_hex("03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap()); // first_per_commitment_point - target_value.append(&mut >::from_hex("02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f").unwrap()); // second_per_commitment_point + target_value.append( + &mut >::from_hex( + "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f", + ) + .unwrap(), + ); // funding_pubkey + target_value.append( + &mut >::from_hex( + "024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766", + ) + .unwrap(), + ); // revocation_basepoint + target_value.append( + &mut >::from_hex( + "02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337", + ) + .unwrap(), + ); // payment_basepoint + target_value.append( + &mut >::from_hex( + "03462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b", + ) + .unwrap(), + ); // delayed_payment_basepoint + target_value.append( + &mut >::from_hex( + "0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7", + ) + .unwrap(), + ); // htlc_basepoint + target_value.append( + &mut >::from_hex( + "03f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a", + ) + .unwrap(), + ); // first_per_commitment_point + target_value.append( + &mut >::from_hex( + "02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f", + ) + .unwrap(), + ); // second_per_commitment_point if shutdown { - target_value.append(&mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap()); + target_value.append( + &mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac") + .unwrap(), + ); } assert_eq!(encoded_value, target_value); } @@ -4606,11 +5062,18 @@ mod tests { #[test] fn encoding_funding_created() { let secp_ctx = Secp256k1::new(); - let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); let funding_created = msgs::FundingCreated { temporary_channel_id: ChannelId::from_bytes([2; 32]), - funding_txid: Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(), + funding_txid: Txid::from_str( + "c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e", + ) + .unwrap(), funding_output_index: 255, signature: sig_1, #[cfg(taproot)] @@ -4626,8 +5089,12 @@ mod tests { #[test] fn encoding_funding_signed() { let secp_ctx = Secp256k1::new(); - let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); let funding_signed = msgs::FundingSigned { channel_id: ChannelId::from_bytes([2; 32]), signature: sig_1, @@ -4642,7 +5109,10 @@ mod tests { #[test] fn encoding_channel_ready() { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1,) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let channel_ready = msgs::ChannelReady { channel_id: ChannelId::from_bytes([2; 32]), next_per_commitment_point: pubkey_1, @@ -4656,7 +5126,10 @@ mod tests { #[test] fn encoding_splice_init() { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1,) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let splice_init = msgs::SpliceInit { channel_id: ChannelId::from_bytes([2; 32]), funding_contribution_satoshis: -123456, @@ -4671,25 +5144,28 @@ mod tests { #[test] fn encoding_stfu() { - let stfu = msgs::Stfu { - channel_id: ChannelId::from_bytes([2; 32]), - initiator: true, - }; + let stfu = msgs::Stfu { channel_id: ChannelId::from_bytes([2; 32]), initiator: true }; let encoded_value = stfu.encode(); - assert_eq!(encoded_value.as_hex().to_string(), "020202020202020202020202020202020202020202020202020202020202020201"); + assert_eq!( + encoded_value.as_hex().to_string(), + "020202020202020202020202020202020202020202020202020202020202020201" + ); - let stfu = msgs::Stfu { - channel_id: ChannelId::from_bytes([3; 32]), - initiator: false, - }; + let stfu = msgs::Stfu { channel_id: ChannelId::from_bytes([3; 32]), initiator: false }; let encoded_value = stfu.encode(); - assert_eq!(encoded_value.as_hex().to_string(), "030303030303030303030303030303030303030303030303030303030303030300"); + assert_eq!( + encoded_value.as_hex().to_string(), + "030303030303030303030303030303030303030303030303030303030303030300" + ); } #[test] fn encoding_splice_ack() { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1,) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let splice_ack = msgs::SpliceAck { channel_id: ChannelId::from_bytes([2; 32]), funding_contribution_satoshis: -123456, @@ -4704,7 +5180,10 @@ mod tests { fn encoding_splice_locked() { let splice_locked = msgs::SpliceLocked { channel_id: ChannelId::from_bytes([2; 32]), - splice_txid: Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(), + splice_txid: Txid::from_str( + "c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e", + ) + .unwrap(), }; let encoded_value = splice_locked.encode(); assert_eq!(encoded_value.as_hex().to_string(), "02020202020202020202020202020202020202020202020202020202020202026e96fe9f8b0ddcd729ba03cfafa5a27b050b39d354dd980814268dfa9a44d4c2"); @@ -4752,7 +5231,10 @@ mod tests { channel_id: ChannelId::from_bytes([2; 32]), serial_id: 4886718345, sats: 4886718345, - script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().assume_checked().script_pubkey(), + script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z") + .unwrap() + .assume_checked() + .script_pubkey(), }; let encoded_value = tx_add_output.encode(); let target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202000000012345678900000001234567890016001436ec78d514df462da95e6a00c24daa8915362d42").unwrap(); @@ -4766,7 +5248,10 @@ mod tests { serial_id: 4886718345, }; let encoded_value = tx_remove_input.encode(); - let target_value = >::from_hex("02020202020202020202020202020202020202020202020202020202020202020000000123456789").unwrap(); + let target_value = >::from_hex( + "02020202020202020202020202020202020202020202020202020202020202020000000123456789", + ) + .unwrap(); assert_eq!(encoded_value, target_value); } @@ -4777,25 +5262,32 @@ mod tests { serial_id: 4886718345, }; let encoded_value = tx_remove_output.encode(); - let target_value = >::from_hex("02020202020202020202020202020202020202020202020202020202020202020000000123456789").unwrap(); + let target_value = >::from_hex( + "02020202020202020202020202020202020202020202020202020202020202020000000123456789", + ) + .unwrap(); assert_eq!(encoded_value, target_value); } #[test] fn encoding_tx_complete() { - let tx_complete = msgs::TxComplete { - channel_id: ChannelId::from_bytes([2; 32]), - }; + let tx_complete = msgs::TxComplete { channel_id: ChannelId::from_bytes([2; 32]) }; let encoded_value = tx_complete.encode(); - let target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); + let target_value = + >::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); assert_eq!(encoded_value, target_value); } #[test] fn encoding_tx_signatures() { let secp_ctx = Secp256k1::new(); - let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); let tx_signatures = msgs::TxSignatures { channel_id: ChannelId::from_bytes([2; 32]), @@ -4811,23 +5303,40 @@ mod tests { shared_input_signature: Some(sig_1), }; let encoded_value = tx_signatures.encode(); - let mut target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); // channel_id - target_value.append(&mut >::from_hex("6e96fe9f8b0ddcd729ba03cfafa5a27b050b39d354dd980814268dfa9a44d4c2").unwrap()); // tx_hash (sha256) (big endian byte order) + let mut target_value = + >::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); // channel_id + target_value.append( + &mut >::from_hex( + "6e96fe9f8b0ddcd729ba03cfafa5a27b050b39d354dd980814268dfa9a44d4c2", + ) + .unwrap(), + ); // tx_hash (sha256) (big endian byte order) target_value.append(&mut >::from_hex("0002").unwrap()); // num_witnesses (u16) - // Witness 1 + // Witness 1 target_value.append(&mut >::from_hex("006b").unwrap()); // len of witness_data target_value.append(&mut >::from_hex("02").unwrap()); // num_witness_elements (VarInt) target_value.append(&mut >::from_hex("47").unwrap()); // len of witness element data (VarInt) target_value.append(&mut >::from_hex("304402206af85b7dd67450ad12c979302fac49dfacbc6a8620f49c5da2b5721cf9565ca502207002b32fed9ce1bf095f57aeb10c36928ac60b12e723d97d2964a54640ceefa701").unwrap()); target_value.append(&mut >::from_hex("21").unwrap()); // len of witness element data (VarInt) - target_value.append(&mut >::from_hex("0301ab7dc16488303549bfcdd80f6ae5ee4c20bf97ab5410bbd6b1bfa85dcd6944").unwrap()); + target_value.append( + &mut >::from_hex( + "0301ab7dc16488303549bfcdd80f6ae5ee4c20bf97ab5410bbd6b1bfa85dcd6944", + ) + .unwrap(), + ); // Witness 2 target_value.append(&mut >::from_hex("006c").unwrap()); // len of witness_data target_value.append(&mut >::from_hex("02").unwrap()); // num_witness_elements (VarInt) target_value.append(&mut >::from_hex("48").unwrap()); // len of witness element data (VarInt) target_value.append(&mut >::from_hex("3045022100ee00dbf4a862463e837d7c08509de814d620e4d9830fa84818713e0fa358f145022021c3c7060c4d53fe84fd165d60208451108a778c13b92ca4c6bad439236126cc01").unwrap()); target_value.append(&mut >::from_hex("21").unwrap()); // len of witness element data (VarInt) - target_value.append(&mut >::from_hex("028fbbf0b16f5ba5bcb5dd37cd4047ce6f726a21c06682f9ec2f52b057de1dbdb5").unwrap()); + target_value.append( + &mut >::from_hex( + "028fbbf0b16f5ba5bcb5dd37cd4047ce6f726a21c06682f9ec2f52b057de1dbdb5", + ) + .unwrap(), + ); target_value.append(&mut >::from_hex("0040").unwrap()); // type and len (64) target_value.append(&mut >::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap()); assert_eq!(encoded_value, target_value); @@ -4838,10 +5347,16 @@ mod tests { channel_id: ChannelId::from_bytes([2; 32]), locktime: 305419896, feerate_sat_per_1000_weight: 20190119, - funding_output_contribution: if let Some((value, _)) = funding_value_with_hex_target { Some(value) } else { None }, + funding_output_contribution: if let Some((value, _)) = funding_value_with_hex_target { + Some(value) + } else { + None + }, }; let encoded_value = tx_init_rbf.encode(); - let mut target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); // channel_id + let mut target_value = + >::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); // channel_id target_value.append(&mut >::from_hex("12345678").unwrap()); // locktime target_value.append(&mut >::from_hex("013413a7").unwrap()); // feerate_sat_per_1000_weight if let Some((_, target)) = funding_value_with_hex_target { @@ -4862,10 +5377,16 @@ mod tests { fn do_encoding_tx_ack_rbf(funding_value_with_hex_target: Option<(i64, &str)>) { let tx_ack_rbf = msgs::TxAckRbf { channel_id: ChannelId::from_bytes([2; 32]), - funding_output_contribution: if let Some((value, _)) = funding_value_with_hex_target { Some(value) } else { None }, + funding_output_contribution: if let Some((value, _)) = funding_value_with_hex_target { + Some(value) + } else { + None + }, }; let encoded_value = tx_ack_rbf.encode(); - let mut target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); + let mut target_value = + >::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); if let Some((_, target)) = funding_value_with_hex_target { target_value.push(0x00); // Type target_value.push(target.len() as u8 / 2); // Length @@ -4894,26 +5415,54 @@ mod tests { fn do_encoding_shutdown(script_type: u8) { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let script = Builder::new().push_opcode(opcodes::OP_TRUE).into_script(); let shutdown = msgs::Shutdown { channel_id: ChannelId::from_bytes([2; 32]), - scriptpubkey: - if script_type == 1 { Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey() } - else if script_type == 2 { Address::p2sh(&script, Network::Testnet).unwrap().script_pubkey() } - else if script_type == 3 { Address::p2wpkh(&::bitcoin::CompressedPublicKey(pubkey_1), Network::Testnet).script_pubkey() } - else { Address::p2wsh(&script, Network::Testnet).script_pubkey() }, + scriptpubkey: if script_type == 1 { + Address::p2pkh( + &::bitcoin::PublicKey { compressed: true, inner: pubkey_1 }, + Network::Testnet, + ) + .script_pubkey() + } else if script_type == 2 { + Address::p2sh(&script, Network::Testnet).unwrap().script_pubkey() + } else if script_type == 3 { + Address::p2wpkh(&::bitcoin::CompressedPublicKey(pubkey_1), Network::Testnet) + .script_pubkey() + } else { + Address::p2wsh(&script, Network::Testnet).script_pubkey() + }, }; let encoded_value = shutdown.encode(); - let mut target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); + let mut target_value = + >::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); if script_type == 1 { - target_value.append(&mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac").unwrap()); + target_value.append( + &mut >::from_hex("001976a91479b000887626b294a914501a4cd226b58b23598388ac") + .unwrap(), + ); } else if script_type == 2 { - target_value.append(&mut >::from_hex("0017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87").unwrap()); + target_value.append( + &mut >::from_hex("0017a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87") + .unwrap(), + ); } else if script_type == 3 { - target_value.append(&mut >::from_hex("0016001479b000887626b294a914501a4cd226b58b235983").unwrap()); + target_value.append( + &mut >::from_hex("0016001479b000887626b294a914501a4cd226b58b235983") + .unwrap(), + ); } else if script_type == 4 { - target_value.append(&mut >::from_hex("002200204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260").unwrap()); + target_value.append( + &mut >::from_hex( + "002200204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260", + ) + .unwrap(), + ); } assert_eq!(encoded_value, target_value); } @@ -4929,8 +5478,12 @@ mod tests { #[test] fn encoding_closing_signed() { let secp_ctx = Secp256k1::new(); - let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); let closing_signed = msgs::ClosingSigned { channel_id: ChannelId::from_bytes([2; 32]), fee_satoshis: 2316138423780173, @@ -4940,7 +5493,10 @@ mod tests { let encoded_value = closing_signed.encode(); let target_value = >::from_hex("020202020202020202020202020202020202020202020202020202020202020200083a840000034dd977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap(); assert_eq!(encoded_value, target_value); - assert_eq!(msgs::ClosingSigned::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(), closing_signed); + assert_eq!( + msgs::ClosingSigned::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(), + closing_signed + ); let closing_signed_with_range = msgs::ClosingSigned { channel_id: ChannelId::from_bytes([2; 32]), @@ -4954,19 +5510,25 @@ mod tests { let encoded_value_with_range = closing_signed_with_range.encode(); let target_value_with_range = >::from_hex("020202020202020202020202020202020202020202020202020202020202020200083a840000034dd977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a011000000000deadbeef1badcafe01234567").unwrap(); assert_eq!(encoded_value_with_range, target_value_with_range); - assert_eq!(msgs::ClosingSigned::read_from_fixed_length_buffer(&mut &target_value_with_range[..]).unwrap(), - closing_signed_with_range); + assert_eq!( + msgs::ClosingSigned::read_from_fixed_length_buffer(&mut &target_value_with_range[..]) + .unwrap(), + closing_signed_with_range + ); } #[test] fn encoding_update_add_htlc() { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let onion_routing_packet = msgs::OnionPacket { version: 255, public_key: Ok(pubkey_1), - hop_data: [1; 20*65], - hmac: [2; 32] + hop_data: [1; 20 * 65], + hmac: [2; 32], }; let update_add_htlc = msgs::UpdateAddHTLC { channel_id: ChannelId::from_bytes([2; 32]), @@ -5004,7 +5566,7 @@ mod tests { attribution_data: Some(AttributionData { hold_times: [3; MAX_HOPS * HOLD_TIME_LEN], hmacs: [3; HMAC_LEN * HMAC_COUNT], - }) + }), }; let encoded_value = update_fail_htlc.encode(); let target_value = >::from_hex("020202020202020202020202020202020202020202020202020202020202020200083a840000034d0020010101010101010101010101010101010101010101010101010101010101010165fd03980303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303").unwrap(); @@ -5017,7 +5579,7 @@ mod tests { channel_id: ChannelId::from_bytes([2; 32]), htlc_id: 2316138423780173, sha256_of_onion: [1; 32], - failure_code: 255 + failure_code: 255, }; let encoded_value = update_fail_malformed_htlc.encode(); let target_value = >::from_hex("020202020202020202020202020202020202020202020202020202020202020200083a840000034d010101010101010101010101010101010101010101010101010101010101010100ff").unwrap(); @@ -5026,19 +5588,41 @@ mod tests { fn do_encoding_commitment_signed(htlcs: bool) { let secp_ctx = Secp256k1::new(); - let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); - let (privkey_2, _) = get_keys_from!("0202020202020202020202020202020202020202020202020202020202020202", secp_ctx); - let (privkey_3, _) = get_keys_from!("0303030303030303030303030303030303030303030303030303030303030303", secp_ctx); - let (privkey_4, _) = get_keys_from!("0404040404040404040404040404040404040404040404040404040404040404", secp_ctx); - let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_2 = get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_3 = get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101")); - let sig_4 = get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101")); + let (privkey_1, _) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); + let (privkey_2, _) = get_keys_from!( + "0202020202020202020202020202020202020202020202020202020202020202", + secp_ctx + ); + let (privkey_3, _) = get_keys_from!( + "0303030303030303030303030303030303030303030303030303030303030303", + secp_ctx + ); + let (privkey_4, _) = get_keys_from!( + "0404040404040404040404040404040404040404040404040404040404040404", + secp_ctx + ); + let sig_1 = + get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_2 = + get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_3 = + get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101")); + let sig_4 = + get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101")); let commitment_signed = msgs::CommitmentSigned { channel_id: ChannelId::from_bytes([2; 32]), signature: sig_1, htlc_signatures: if htlcs { vec![sig_2, sig_3, sig_4] } else { Vec::new() }, - batch: Some(msgs::CommitmentSignedBatch { batch_size: 3, funding_txid: Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap() }), + batch: Some(msgs::CommitmentSignedBatch { + batch_size: 3, + funding_txid: Txid::from_str( + "c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e", + ) + .unwrap(), + }), #[cfg(taproot)] partial_signature_with_nonce: None, }; @@ -5062,10 +5646,16 @@ mod tests { #[test] fn encoding_revoke_and_ack() { let secp_ctx = Secp256k1::new(); - let (_, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_, pubkey_1) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let raa = msgs::RevokeAndACK { channel_id: ChannelId::from_bytes([2; 32]), - per_commitment_secret: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + per_commitment_secret: [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, + ], next_per_commitment_point: pubkey_1, #[cfg(taproot)] next_local_nonce: None, @@ -5082,7 +5672,10 @@ mod tests { feerate_per_kw: 20190119, }; let encoded_value = update_fee.encode(); - let target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202013413a7").unwrap(); + let target_value = >::from_hex( + "0202020202020202020202020202020202020202020202020202020202020202013413a7", + ) + .unwrap(); assert_eq!(encoded_value, target_value); } @@ -5094,22 +5687,34 @@ mod tests { networks: Some(vec![mainnet_hash]), remote_network_address: None, }.encode(), >::from_hex("00023fff0003ffffff01206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); - assert_eq!(msgs::Init { - features: InitFeatures::from_le_bytes(vec![0xFF]), - networks: None, - remote_network_address: None, - }.encode(), >::from_hex("0001ff0001ff").unwrap()); - assert_eq!(msgs::Init { - features: InitFeatures::from_le_bytes(vec![]), - networks: Some(vec![mainnet_hash]), - remote_network_address: None, - }.encode(), >::from_hex("0000000001206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); + assert_eq!( + msgs::Init { + features: InitFeatures::from_le_bytes(vec![0xFF]), + networks: None, + remote_network_address: None, + } + .encode(), + >::from_hex("0001ff0001ff").unwrap() + ); + assert_eq!( + msgs::Init { + features: InitFeatures::from_le_bytes(vec![]), + networks: Some(vec![mainnet_hash]), + remote_network_address: None, + } + .encode(), + >::from_hex( + "0000000001206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000" + ) + .unwrap() + ); assert_eq!(msgs::Init { features: InitFeatures::from_le_bytes(vec![]), networks: Some(vec![ChainHash::from(&[1; 32]), ChainHash::from(&[2; 32])]), remote_network_address: None, }.encode(), >::from_hex("00000000014001010101010101010101010101010101010101010101010101010101010101010202020202020202020202020202020202020202020202020202020202020202").unwrap()); - let init_msg = msgs::Init { features: InitFeatures::from_le_bytes(vec![]), + let init_msg = msgs::Init { + features: InitFeatures::from_le_bytes(vec![]), networks: Some(vec![mainnet_hash]), remote_network_address: Some(SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], @@ -5119,7 +5724,10 @@ mod tests { let encoded_value = init_msg.encode(); let target_value = >::from_hex("0000000001206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d61900000000000307017f00000103e8").unwrap(); assert_eq!(encoded_value, target_value); - assert_eq!(msgs::Init::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(), init_msg); + assert_eq!( + msgs::Init::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(), + init_msg + ); } #[test] @@ -5146,10 +5754,7 @@ mod tests { #[test] fn encoding_ping() { - let ping = msgs::Ping { - ponglen: 64, - byteslen: 64 - }; + let ping = msgs::Ping { ponglen: 64, byteslen: 64 }; let encoded_value = ping.encode(); let target_value = >::from_hex("0040004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); assert_eq!(encoded_value, target_value); @@ -5157,9 +5762,8 @@ mod tests { #[test] fn encoding_peer_storage() { - let peer_storage = msgs::PeerStorage { - data: >::from_hex("01020304050607080910").unwrap() - }; + let peer_storage = + msgs::PeerStorage { data: >::from_hex("01020304050607080910").unwrap() }; let encoded_value = peer_storage.encode(); let target_value = >::from_hex("000a01020304050607080910").unwrap(); assert_eq!(encoded_value, target_value); @@ -5168,7 +5772,7 @@ mod tests { #[test] fn encoding_peer_storage_retrieval() { let peer_storage_retrieval = msgs::PeerStorageRetrieval { - data: >::from_hex("01020304050607080910").unwrap() + data: >::from_hex("01020304050607080910").unwrap(), }; let encoded_value = peer_storage_retrieval.encode(); let target_value = >::from_hex("000a01020304050607080910").unwrap(); @@ -5177,9 +5781,7 @@ mod tests { #[test] fn encoding_pong() { - let pong = msgs::Pong { - byteslen: 64 - }; + let pong = msgs::Pong { byteslen: 64 }; let encoded_value = pong.encode(); let target_value = >::from_hex("004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); assert_eq!(encoded_value, target_value); @@ -5193,18 +5795,25 @@ mod tests { outgoing_cltv_value: 0xffffffff, }; let encoded_value = outbound_msg.encode(); - let target_value = >::from_hex("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap(); + let target_value = + >::from_hex("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap(); assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); + let inbound_msg = + ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); if let msgs::InboundOnionPayload::Forward(InboundOnionForwardPayload { - short_channel_id, amt_to_forward, outgoing_cltv_value - }) = inbound_msg { + short_channel_id, + amt_to_forward, + outgoing_cltv_value, + }) = inbound_msg + { assert_eq!(short_channel_id, 0xdeadbeef1bad1dea); assert_eq!(amt_to_forward, 0x0badf00d01020304); assert_eq!(outgoing_cltv_value, 0xffffffff); - } else { panic!(); } + } else { + panic!(); + } } #[test] @@ -5222,13 +5831,20 @@ mod tests { assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); + let inbound_msg = + ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); if let msgs::InboundOnionPayload::Receive(InboundOnionReceivePayload { - payment_data: None, sender_intended_htlc_amt_msat, cltv_expiry_height, .. - }) = inbound_msg { + payment_data: None, + sender_intended_htlc_amt_msat, + cltv_expiry_height, + .. + }) = inbound_msg + { assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304); assert_eq!(cltv_expiry_height, 0xffffffff); - } else { panic!(); } + } else { + panic!(); + } } #[test] @@ -5237,7 +5853,7 @@ mod tests { let outbound_msg = msgs::OutboundOnionPayload::Receive { payment_data: Some(FinalOnionHopData { payment_secret: expected_payment_secret, - total_msat: 0x1badca1f + total_msat: 0x1badca1f, }), payment_metadata: None, keysend_preimage: None, @@ -5250,32 +5866,31 @@ mod tests { assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); + let inbound_msg = + ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); if let msgs::InboundOnionPayload::Receive(InboundOnionReceivePayload { - payment_data: Some(FinalOnionHopData { - payment_secret, - total_msat: 0x1badca1f - }), - sender_intended_htlc_amt_msat, cltv_expiry_height, + payment_data: Some(FinalOnionHopData { payment_secret, total_msat: 0x1badca1f }), + sender_intended_htlc_amt_msat, + cltv_expiry_height, payment_metadata: None, keysend_preimage: None, custom_tlvs, - }) = inbound_msg { + }) = inbound_msg + { assert_eq!(payment_secret, expected_payment_secret); assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304); assert_eq!(cltv_expiry_height, 0xffffffff); assert_eq!(custom_tlvs, vec![]); - } else { panic!(); } + } else { + panic!(); + } } #[test] fn encoding_final_onion_hop_data_with_bad_custom_tlvs() { // If custom TLVs have type number within the range reserved for protocol, treat them as if // they're unknown - let bad_type_range_tlvs = vec![ - ((1 << 16) - 4, vec![42]), - ((1 << 16) - 2, vec![42; 32]), - ]; + let bad_type_range_tlvs = vec![((1 << 16) - 4, vec![42]), ((1 << 16) - 2, vec![42; 32])]; let mut msg = msgs::OutboundOnionPayload::Receive { payment_data: None, payment_metadata: None, @@ -5286,28 +5901,30 @@ mod tests { }; let encoded_value = msg.encode(); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..]), (None, &node_signer)).is_err()); - let good_type_range_tlvs = vec![ - ((1 << 16) - 3, vec![42]), - ((1 << 16) - 1, vec![42; 32]), - ]; + assert!(msgs::InboundOnionPayload::read( + &mut Cursor::new(&encoded_value[..]), + (None, &node_signer) + ) + .is_err()); + let good_type_range_tlvs = vec![((1 << 16) - 3, vec![42]), ((1 << 16) - 1, vec![42; 32])]; if let msgs::OutboundOnionPayload::Receive { ref mut custom_tlvs, .. } = msg { *custom_tlvs = &good_type_range_tlvs; } let encoded_value = msg.encode(); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), (None, &node_signer)).unwrap(); + let inbound_msg = + ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), (None, &node_signer)).unwrap(); match inbound_msg { - msgs::InboundOnionPayload::Receive(InboundOnionReceivePayload { custom_tlvs, .. }) => assert!(custom_tlvs.is_empty()), + msgs::InboundOnionPayload::Receive(InboundOnionReceivePayload { + custom_tlvs, .. + }) => assert!(custom_tlvs.is_empty()), _ => panic!(), } } #[test] fn encoding_final_onion_hop_data_with_custom_tlvs() { - let expected_custom_tlvs = vec![ - (5482373483, vec![0x12, 0x34]), - (5482373487, vec![0x42u8; 8]), - ]; + let expected_custom_tlvs = + vec![(5482373483, vec![0x12, 0x34]), (5482373487, vec![0x42u8; 8])]; let msg = msgs::OutboundOnionPayload::Receive { payment_data: None, payment_metadata: None, @@ -5320,7 +5937,8 @@ mod tests { let target_value = >::from_hex("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap(); assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg: msgs::InboundOnionPayload = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); + let inbound_msg: msgs::InboundOnionPayload = + ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &node_signer)).unwrap(); if let msgs::InboundOnionPayload::Receive(InboundOnionReceivePayload { payment_data: None, payment_metadata: None, @@ -5329,17 +5947,23 @@ mod tests { sender_intended_htlc_amt_msat, cltv_expiry_height: outgoing_cltv_value, .. - }) = inbound_msg { + }) = inbound_msg + { assert_eq!(custom_tlvs, expected_custom_tlvs); assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304); assert_eq!(outgoing_cltv_value, 0xffffffff); - } else { panic!(); } + } else { + panic!(); + } } #[test] fn encoding_final_onion_hop_data_with_trampoline_packet() { let secp_ctx = Secp256k1::new(); - let (_private_key, public_key) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let (_private_key, public_key) = get_keys_from!( + "0101010101010101010101010101010101010101010101010101010101010101", + secp_ctx + ); let compressed_public_key = public_key.serialize(); assert_eq!(compressed_public_key.len(), 33); @@ -5353,11 +5977,13 @@ mod tests { let encoded_trampoline_packet = trampoline_packet.encode(); assert_eq!(encoded_trampoline_packet.len(), 716); - { // verify that a codec round trip works + { + // verify that a codec round trip works let decoded_trampoline_packet: TrampolineOnionPacket = ::read_from_fixed_length_buffer( - &mut &encoded_trampoline_packet[..] - ).unwrap(); + &mut &encoded_trampoline_packet[..], + ) + .unwrap(); assert_eq!(decoded_trampoline_packet.encode(), encoded_trampoline_packet); } @@ -5371,32 +5997,37 @@ mod tests { let trampoline_type_bytes = &encoded_payload[19..=19]; let mut trampoline_type_cursor = Cursor::new(trampoline_type_bytes); - let trampoline_type_big_size: BigSize = Readable::read(&mut trampoline_type_cursor).unwrap(); + let trampoline_type_big_size: BigSize = + Readable::read(&mut trampoline_type_cursor).unwrap(); assert_eq!(trampoline_type_big_size.0, 20); let trampoline_length_bytes = &encoded_payload[20..=22]; let mut trampoline_length_cursor = Cursor::new(trampoline_length_bytes); - let trampoline_length_big_size: BigSize = Readable::read(&mut trampoline_length_cursor).unwrap(); + let trampoline_length_big_size: BigSize = + Readable::read(&mut trampoline_length_cursor).unwrap(); assert_eq!(trampoline_length_big_size.0, encoded_trampoline_packet.len() as u64); } #[test] fn encoding_final_onion_hop_data_with_eclair_trampoline_packet() { - let public_key = PublicKey::from_slice(&>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()).unwrap(); + let public_key = PublicKey::from_slice( + &>::from_hex( + "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619", + ) + .unwrap(), + ) + .unwrap(); let hop_data = >::from_hex("cff34152f3a36e52ca94e74927203a560392b9cc7ce3c45809c6be52166c24a595716880f95f178bf5b30ca63141f74db6e92795c6130877cfdac3d4bd3087ee73c65d627ddd709112a848cc99e303f3706509aa43ba7c8a88cba175fccf9a8f5016ef06d3b935dbb15196d7ce16dc1a7157845566901d7b2197e52cab4ce487014b14816e5805f9fcacb4f8f88b8ff176f1b94f6ce6b00bc43221130c17d20ef629db7c5f7eafaa166578c720619561dd14b3277db557ec7dcdb793771aef0f2f667cfdbeae3ac8d331c5994779dffb31e5fc0dbdedc0c592ca6d21c18e47fe3528d6975c19517d7e2ea8c5391cf17d0fe30c80913ed887234ccb48808f7ef9425bcd815c3b586210979e3bb286ef2851bf9ce04e28c40a203df98fd648d2f1936fd2f1def0e77eecb277229b4b682322371c0a1dbfcd723a991993df8cc1f2696b84b055b40a1792a29f710295a18fbd351b0f3ff34cd13941131b8278ba79303c89117120eea691738a9954908195143b039dbeed98f26a92585f3d15cf742c953799d3272e0545e9b744be9d3b4c").unwrap(); - let hmac_vector = >::from_hex("bb079bfc4b35190eee9f59a1d7b41ba2f773179f322dafb4b1af900c289ebd6c").unwrap(); + let hmac_vector = + >::from_hex("bb079bfc4b35190eee9f59a1d7b41ba2f773179f322dafb4b1af900c289ebd6c") + .unwrap(); let mut hmac = [0; 32]; hmac.copy_from_slice(&hmac_vector); let compressed_public_key = public_key.serialize(); assert_eq!(compressed_public_key.len(), 33); - let trampoline_packet = TrampolineOnionPacket { - version: 0, - public_key, - hop_data, - hmac, - }; + let trampoline_packet = TrampolineOnionPacket { version: 0, public_key, hop_data, hmac }; let encoded_trampoline_packet = trampoline_packet.encode(); let expected_eclair_trampoline_packet = >::from_hex("0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619cff34152f3a36e52ca94e74927203a560392b9cc7ce3c45809c6be52166c24a595716880f95f178bf5b30ca63141f74db6e92795c6130877cfdac3d4bd3087ee73c65d627ddd709112a848cc99e303f3706509aa43ba7c8a88cba175fccf9a8f5016ef06d3b935dbb15196d7ce16dc1a7157845566901d7b2197e52cab4ce487014b14816e5805f9fcacb4f8f88b8ff176f1b94f6ce6b00bc43221130c17d20ef629db7c5f7eafaa166578c720619561dd14b3277db557ec7dcdb793771aef0f2f667cfdbeae3ac8d331c5994779dffb31e5fc0dbdedc0c592ca6d21c18e47fe3528d6975c19517d7e2ea8c5391cf17d0fe30c80913ed887234ccb48808f7ef9425bcd815c3b586210979e3bb286ef2851bf9ce04e28c40a203df98fd648d2f1936fd2f1def0e77eecb277229b4b682322371c0a1dbfcd723a991993df8cc1f2696b84b055b40a1792a29f710295a18fbd351b0f3ff34cd13941131b8278ba79303c89117120eea691738a9954908195143b039dbeed98f26a92585f3d15cf742c953799d3272e0545e9b744be9d3b4cbb079bfc4b35190eee9f59a1d7b41ba2f773179f322dafb4b1af900c289ebd6c").unwrap(); assert_eq!(encoded_trampoline_packet, expected_eclair_trampoline_packet); @@ -5406,26 +6037,36 @@ mod tests { fn encoding_outbound_trampoline_payload() { let mut trampoline_features = Bolt12InvoiceFeatures::empty(); trampoline_features.set_basic_mpp_optional(); - let introduction_node = PublicKey::from_slice(&>::from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()).unwrap(); - let blinding_point = PublicKey::from_slice(&>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()).unwrap(); + let introduction_node = PublicKey::from_slice( + &>::from_hex( + "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991", + ) + .unwrap(), + ) + .unwrap(); + let blinding_point = PublicKey::from_slice( + &>::from_hex( + "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619", + ) + .unwrap(), + ) + .unwrap(); let trampoline_payload = OutboundTrampolinePayload::LegacyBlindedPathEntry { amt_to_forward: 150_000_000, outgoing_cltv_value: 800_000, - payment_paths: vec![ - BlindedPaymentPath::from_raw( - introduction_node, - blinding_point, - vec![], - BlindedPayInfo{ - fee_base_msat: 500, - fee_proportional_millionths: 1_000, - cltv_expiry_delta: 36, - htlc_minimum_msat: 1, - htlc_maximum_msat: 500_000_000, - features: BlindedHopFeatures::empty(), - } - ) - ], + payment_paths: vec![BlindedPaymentPath::from_raw( + introduction_node, + blinding_point, + vec![], + BlindedPayInfo { + fee_base_msat: 500, + fee_proportional_millionths: 1_000, + cltv_expiry_delta: 36, + htlc_minimum_msat: 1, + htlc_maximum_msat: 500_000_000, + features: BlindedHopFeatures::empty(), + }, + )], invoice_features: Some(trampoline_features), }; let serialized_payload = trampoline_payload.encode().to_lower_hex_string(); @@ -5456,11 +6097,8 @@ mod tests { #[test] fn query_channel_range_end_blocknum() { - let tests: Vec<(u32, u32, u32)> = vec![ - (10000, 1500, 11500), - (0, 0xffffffff, 0xffffffff), - (1, 0xffffffff, 0xffffffff), - ]; + let tests: Vec<(u32, u32, u32)> = + vec![(10000, 1500, 11500), (0, 0xffffffff, 0xffffffff), (1, 0xffffffff, 0xffffffff)]; for (first_blocknum, number_of_blocks, expected) in tests.into_iter() { let sut = msgs::QueryChannelRange { @@ -5480,10 +6118,14 @@ mod tests { number_of_blocks: 1500, }; let encoded_value = query_channel_range.encode(); - let target_value = >::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000186a0000005dc").unwrap(); + let target_value = >::from_hex( + "06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000186a0000005dc", + ) + .unwrap(); assert_eq!(encoded_value, target_value); - query_channel_range = LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); + query_channel_range = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); assert_eq!(query_channel_range.first_blocknum, 100000); assert_eq!(query_channel_range.number_of_blocks, 1500); } @@ -5495,7 +6137,10 @@ mod tests { } fn do_encoding_reply_channel_range(encoding_type: u8) { - let mut target_value = >::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000b8a06000005dc01").unwrap(); + let mut target_value = >::from_hex( + "06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000b8a06000005dc01", + ) + .unwrap(); let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest); let mut reply_channel_range = msgs::ReplyChannelRange { chain_hash: expected_chain_hash, @@ -5506,11 +6151,15 @@ mod tests { }; if encoding_type == 0 { - target_value.append(&mut >::from_hex("001900000000000000008e0000000000003c69000000000045a6c4").unwrap()); + target_value.append( + &mut >::from_hex("001900000000000000008e0000000000003c69000000000045a6c4") + .unwrap(), + ); let encoded_value = reply_channel_range.encode(); assert_eq!(encoded_value, target_value); - reply_channel_range = LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); + reply_channel_range = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); assert_eq!(reply_channel_range.chain_hash, expected_chain_hash); assert_eq!(reply_channel_range.first_blocknum, 756230); assert_eq!(reply_channel_range.number_of_blocks, 1500); @@ -5519,8 +6168,12 @@ mod tests { assert_eq!(reply_channel_range.short_channel_ids[1], 0x0000000000003c69); assert_eq!(reply_channel_range.short_channel_ids[2], 0x000000000045a6c4); } else { - target_value.append(&mut >::from_hex("001601789c636000833e08659309a65878be010010a9023a").unwrap()); - let result: Result = LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]); + target_value.append( + &mut >::from_hex("001601789c636000833e08659309a65878be010010a9023a") + .unwrap(), + ); + let result: Result = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]); assert!(result.is_err(), "Expected decode failure with unsupported zlib encoding"); } } @@ -5532,7 +6185,9 @@ mod tests { } fn do_encoding_query_short_channel_ids(encoding_type: u8) { - let mut target_value = >::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap(); + let mut target_value = + >::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f") + .unwrap(); let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest); let mut query_short_channel_ids = msgs::QueryShortChannelIds { chain_hash: expected_chain_hash, @@ -5540,18 +6195,26 @@ mod tests { }; if encoding_type == 0 { - target_value.append(&mut >::from_hex("001900000000000000008e0000000000003c69000000000045a6c4").unwrap()); + target_value.append( + &mut >::from_hex("001900000000000000008e0000000000003c69000000000045a6c4") + .unwrap(), + ); let encoded_value = query_short_channel_ids.encode(); assert_eq!(encoded_value, target_value); - query_short_channel_ids = LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); + query_short_channel_ids = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); assert_eq!(query_short_channel_ids.chain_hash, expected_chain_hash); assert_eq!(query_short_channel_ids.short_channel_ids[0], 0x000000000000008e); assert_eq!(query_short_channel_ids.short_channel_ids[1], 0x0000000000003c69); assert_eq!(query_short_channel_ids.short_channel_ids[2], 0x000000000045a6c4); } else { - target_value.append(&mut >::from_hex("001601789c636000833e08659309a65878be010010a9023a").unwrap()); - let result: Result = LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]); + target_value.append( + &mut >::from_hex("001601789c636000833e08659309a65878be010010a9023a") + .unwrap(), + ); + let result: Result = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]); assert!(result.is_err(), "Expected decode failure with unsupported zlib encoding"); } } @@ -5564,16 +6227,20 @@ mod tests { full_information: true, }; let encoded_value = reply_short_channel_ids_end.encode(); - let target_value = >::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f01").unwrap(); + let target_value = >::from_hex( + "06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f01", + ) + .unwrap(); assert_eq!(encoded_value, target_value); - reply_short_channel_ids_end = LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); + reply_short_channel_ids_end = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); assert_eq!(reply_short_channel_ids_end.chain_hash, expected_chain_hash); assert_eq!(reply_short_channel_ids_end.full_information, true); } #[test] - fn encoding_gossip_timestamp_filter(){ + fn encoding_gossip_timestamp_filter() { let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest); let mut gossip_timestamp_filter = msgs::GossipTimestampFilter { chain_hash: expected_chain_hash, @@ -5581,12 +6248,14 @@ mod tests { timestamp_range: 0xffff_ffff, }; let encoded_value = gossip_timestamp_filter.encode(); - let target_value = >::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f5ec57980ffffffff").unwrap(); + let target_value = >::from_hex( + "06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f5ec57980ffffffff", + ) + .unwrap(); assert_eq!(encoded_value, target_value); - gossip_timestamp_filter = LengthReadable::read_from_fixed_length_buffer( - &mut &target_value[..] - ).unwrap(); + gossip_timestamp_filter = + LengthReadable::read_from_fixed_length_buffer(&mut &target_value[..]).unwrap(); assert_eq!(gossip_timestamp_filter.chain_hash, expected_chain_hash); assert_eq!(gossip_timestamp_filter.first_timestamp, 1590000000); assert_eq!(gossip_timestamp_filter.timestamp_range, 0xffff_ffff); @@ -5605,8 +6274,11 @@ mod tests { let mut rd = Cursor::new(&big_payload[..]); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - , &test_utils::TestKeysInterface)>> - ::read(&mut rd, (None, &&node_signer)).unwrap(); + , + &test_utils::TestKeysInterface, + )>>::read(&mut rd, (None, &&node_signer)) + .unwrap(); } // see above test, needs to be a separate method for use of the serialization macros. fn encode_big_payload() -> Result, io::Error> { @@ -5618,7 +6290,12 @@ mod tests { }; let mut encoded_payload = Vec::new(); let test_bytes = vec![42u8; 1000]; - if let msgs::OutboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = payload { + if let msgs::OutboundOnionPayload::Forward { + short_channel_id, + amt_to_forward, + outgoing_cltv_value, + } = payload + { _encode_varint_length_prefixed_tlv!(&mut encoded_payload, { (1, &test_bytes, required_vec), (2, HighZeroBytesDroppedBigSize(amt_to_forward), required), @@ -5632,10 +6309,8 @@ mod tests { #[test] #[cfg(feature = "std")] fn test_socket_address_from_str() { - let tcpip_v4 = SocketAddress::TcpIpV4 { - addr: Ipv4Addr::new(127, 0, 0, 1).octets(), - port: 1234, - }; + let tcpip_v4 = + SocketAddress::TcpIpV4 { addr: Ipv4Addr::new(127, 0, 0, 1).octets(), port: 1234 }; assert_eq!(tcpip_v4, SocketAddress::from_str("127.0.0.1:1234").unwrap()); assert_eq!(tcpip_v4, SocketAddress::from_str(&tcpip_v4.to_string()).unwrap()); @@ -5647,55 +6322,110 @@ mod tests { assert_eq!(tcpip_v6, SocketAddress::from_str(&tcpip_v6.to_string()).unwrap()); let hostname = SocketAddress::Hostname { - hostname: Hostname::try_from("lightning-node.mydomain.com".to_string()).unwrap(), - port: 1234, + hostname: Hostname::try_from("lightning-node.mydomain.com".to_string()).unwrap(), + port: 1234, }; assert_eq!(hostname, SocketAddress::from_str("lightning-node.mydomain.com:1234").unwrap()); assert_eq!(hostname, SocketAddress::from_str(&hostname.to_string()).unwrap()); - let onion_v2 = SocketAddress::OnionV2 ([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7],); - assert_eq!("OnionV2([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7])", &onion_v2.to_string()); - assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("FACEBOOKCOREWWWI.onion:9735")); + let onion_v2 = SocketAddress::OnionV2([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7]); + assert_eq!( + "OnionV2([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7])", + &onion_v2.to_string() + ); + assert_eq!( + Err(SocketAddressParseError::InvalidOnionV3), + SocketAddress::from_str("FACEBOOKCOREWWWI.onion:9735") + ); let onion_v3 = SocketAddress::OnionV3 { - ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107, 4, 105, 247, 246, 85, - 111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, 33, 71, 3], + ed25519_pubkey: [ + 37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107, 4, 105, 247, 246, 85, 111, + 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, 33, 71, 3, + ], checksum: 48326, version: 121, - port: 1234 + port: 1234, }; - assert_eq!(onion_v3, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap()); + assert_eq!( + onion_v3, + SocketAddress::from_str( + "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" + ) + .unwrap() + ); assert_eq!(onion_v3, SocketAddress::from_str(&onion_v3.to_string()).unwrap()); - assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234")); - assert_eq!(Err(SocketAddressParseError::InvalidInput), SocketAddress::from_str("127.0.0.1@1234")); + assert_eq!( + Err(SocketAddressParseError::InvalidOnionV3), + SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234") + ); + assert_eq!( + Err(SocketAddressParseError::InvalidInput), + SocketAddress::from_str("127.0.0.1@1234") + ); assert_eq!(Err(SocketAddressParseError::InvalidInput), "".parse::()); - assert!(SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:9735:94").is_err()); + assert!(SocketAddress::from_str( + "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:9735:94" + ) + .is_err()); assert!(SocketAddress::from_str("wrong$%#.com:1234").is_err()); - assert_eq!(Err(SocketAddressParseError::InvalidPort), SocketAddress::from_str("example.com:wrong")); + assert_eq!( + Err(SocketAddressParseError::InvalidPort), + SocketAddress::from_str("example.com:wrong") + ); assert!("localhost".parse::().is_err()); assert!("localhost:invalid-port".parse::().is_err()); - assert!( "invalid-onion-v3-hostname.onion:8080".parse::().is_err()); + assert!("invalid-onion-v3-hostname.onion:8080".parse::().is_err()); assert!("b32.example.onion:invalid-port".parse::().is_err()); assert!("invalid-address".parse::().is_err()); - assert!(SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:1234").is_err()); + assert!(SocketAddress::from_str( + "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:1234" + ) + .is_err()); } #[test] #[cfg(feature = "std")] fn test_socket_address_to_socket_addrs() { - assert_eq!(SocketAddress::TcpIpV4 {addr:[0u8; 4], port: 1337,}.to_socket_addrs().unwrap().next().unwrap(), - SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0,0,0,0), 1337))); - assert_eq!(SocketAddress::TcpIpV6 {addr:[0u8; 16], port: 1337,}.to_socket_addrs().unwrap().next().unwrap(), - SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from([0u8; 16]), 1337, 0, 0))); - assert_eq!(SocketAddress::Hostname { hostname: Hostname::try_from("0.0.0.0".to_string()).unwrap(), port: 0 } - .to_socket_addrs().unwrap().next().unwrap(), SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0u8; 4]),0))); + assert_eq!( + SocketAddress::TcpIpV4 { addr: [0u8; 4], port: 1337 } + .to_socket_addrs() + .unwrap() + .next() + .unwrap(), + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1337)) + ); + assert_eq!( + SocketAddress::TcpIpV6 { addr: [0u8; 16], port: 1337 } + .to_socket_addrs() + .unwrap() + .next() + .unwrap(), + SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from([0u8; 16]), 1337, 0, 0)) + ); + assert_eq!( + SocketAddress::Hostname { + hostname: Hostname::try_from("0.0.0.0".to_string()).unwrap(), + port: 0, + } + .to_socket_addrs() + .unwrap() + .next() + .unwrap(), + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0u8; 4]), 0)) + ); assert!(SocketAddress::OnionV2([0u8; 12]).to_socket_addrs().is_err()); - assert!(SocketAddress::OnionV3{ ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102, - 182, 107, 4, 105, 247, 246, 85, 111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, - 33, 71, 3], + assert!(SocketAddress::OnionV3 { + ed25519_pubkey: [ + 37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107, 4, 105, 247, 246, 85, 111, + 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, 33, 71, 3 + ], checksum: 48326, version: 121, - port: 1234 }.to_socket_addrs().is_err()); + port: 1234 + } + .to_socket_addrs() + .is_err()); } } diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index de717db86ae..fa7c8ced96f 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -21,7 +21,6 @@ lightning/src/ln/invoice_utils.rs lightning/src/ln/max_payment_path_len_tests.rs lightning/src/ln/mod.rs lightning/src/ln/monitor_tests.rs -lightning/src/ln/msgs.rs lightning/src/ln/offers_tests.rs lightning/src/ln/onion_payment.rs lightning/src/ln/onion_route_tests.rs From facdc724e26e316ee32eafbe297592cc8ffe7b47 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 2 May 2025 20:45:49 +0000 Subject: [PATCH 03/11] Cleanup `msgs.rs` rather trivially after rustfmt'ing it --- lightning/src/ln/msgs.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 65ba485c9c5..8c5b4335195 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -1108,15 +1108,15 @@ impl std::net::ToSocketAddrs for SocketAddress { }, SocketAddress::Hostname { ref hostname, port } => { (hostname.as_str(), *port).to_socket_addrs() - } - SocketAddress::OnionV2(..) => { - Err(std::io::Error::new(std::io::ErrorKind::Other, "Resolution of OnionV2 \ - addresses is currently unsupported.")) - } - SocketAddress::OnionV3 { .. } => { - Err(std::io::Error::new(std::io::ErrorKind::Other, "Resolution of OnionV3 \ - addresses is currently unsupported.")) - } + }, + SocketAddress::OnionV2(..) => Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Resolution of OnionV2 addresses is currently unsupported.", + )), + SocketAddress::OnionV3 { .. } => Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Resolution of OnionV3 addresses is currently unsupported.", + )), } } } From ed28eeea97bd68608d762d8497564c1f1462383d Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 2 May 2025 20:45:52 +0000 Subject: [PATCH 04/11] f additional cleanup --- lightning/src/ln/msgs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 8c5b4335195..2e9c3b90957 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -5313,7 +5313,8 @@ mod tests { .unwrap(), ); // tx_hash (sha256) (big endian byte order) target_value.append(&mut >::from_hex("0002").unwrap()); // num_witnesses (u16) - // Witness 1 + + // Witness 1 target_value.append(&mut >::from_hex("006b").unwrap()); // len of witness_data target_value.append(&mut >::from_hex("02").unwrap()); // num_witness_elements (VarInt) target_value.append(&mut >::from_hex("47").unwrap()); // len of witness element data (VarInt) From 5d606e8d85bad26a4f3c083682cfba3cb9691486 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 20:32:23 +0000 Subject: [PATCH 05/11] Pull hex constants out in `peer_channel_encryptor` tests Via sed: s/\(\t*\)\(.*\)>::from_hex(\(["0-9a-f]*\)).unwrap()/\1let hex = \3;\r\1\2>::from_hex(hex).unwrap()/g --- lightning/src/ln/peer_channel_encryptor.rs | 159 ++++++++++++++------- 1 file changed, 106 insertions(+), 53 deletions(-) diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index 00e45afb4d8..5d935570595 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -578,39 +578,52 @@ mod tests { use crate::util::test_utils::TestNodeSigner; fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor { - let their_node_id = PublicKey::from_slice(&>::from_hex("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap(); + let hex = "028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7"; + let their_node_id = PublicKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); let secp_ctx = Secp256k1::signing_only(); - let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&>::from_hex("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap()); - assert_eq!(outbound_peer.get_act_one(&secp_ctx)[..], >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap()[..]); + let hex = "1212121212121212121212121212121212121212121212121212121212121212"; + let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap()); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + assert_eq!(outbound_peer.get_act_one(&secp_ctx)[..], >::from_hex(hex).unwrap()[..]); outbound_peer } fn get_inbound_peer_for_test_vectors() -> PeerChannelEncryptor { // transport-responder successful handshake - let our_node_id = SecretKey::from_slice(&>::from_hex("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&>::from_hex("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); + let hex = "2121212121212121212121212121212121212121212121212121212121212121"; + let our_node_id = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); + let hex = "2222222222222222222222222222222222222222222222222222222222222222"; + let our_ephemeral = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); let secp_ctx = Secp256k1::new(); let node_signer = TestNodeSigner::new(our_node_id); let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one = >::from_hex(hex).unwrap().to_vec(); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); - let act_three = >::from_hex("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); + let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; + let act_three = >::from_hex(hex).unwrap().to_vec(); // test vector doesn't specify the initiator static key, but it's the same as the one // from transport-initiator successful handshake - assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], >::from_hex("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa").unwrap()[..]); + let hex = "034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"; + assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], >::from_hex(hex).unwrap()[..]); match inbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, >::from_hex("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); + let hex = "bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442"; + assert_eq!(sk, >::from_hex(hex).unwrap()[..]); assert_eq!(sn, 0); - assert_eq!(sck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, >::from_hex("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); + let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; + assert_eq!(sck, >::from_hex(hex).unwrap()[..]); + let hex = "969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9"; + assert_eq!(rk, >::from_hex(hex).unwrap()[..]); assert_eq!(rn, 0); - assert_eq!(rck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); + let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; + assert_eq!(rck, >::from_hex(hex).unwrap()[..]); }, _ => panic!() } @@ -620,24 +633,31 @@ mod tests { #[test] fn noise_initiator_test_vectors() { - let our_node_id = SecretKey::from_slice(&>::from_hex("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); + let hex = "1111111111111111111111111111111111111111111111111111111111111111"; + let our_node_id = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); let node_signer = TestNodeSigner::new(our_node_id); { // transport-initiator successful handshake let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let act_two = >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], >::from_hex("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + let act_two = >::from_hex(hex).unwrap().to_vec(); + let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; + assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], >::from_hex(hex).unwrap()[..]); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, >::from_hex("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); + let hex = "969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9"; + assert_eq!(sk, >::from_hex(hex).unwrap()[..]); assert_eq!(sn, 0); - assert_eq!(sck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, >::from_hex("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); + let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; + assert_eq!(sck, >::from_hex(hex).unwrap()[..]); + let hex = "bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442"; + assert_eq!(rk, >::from_hex(hex).unwrap()[..]); assert_eq!(rn, 0); - assert_eq!(rck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); + let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; + assert_eq!(rck, >::from_hex(hex).unwrap()[..]); }, _ => panic!() } @@ -650,7 +670,8 @@ mod tests { // transport-initiator act2 bad version test let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let act_two = >::from_hex("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); + let hex = "0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + let act_two = >::from_hex(hex).unwrap().to_vec(); assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err()); } @@ -658,7 +679,8 @@ mod tests { // transport-initiator act2 bad key serialization test let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let act_two = >::from_hex("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); + let hex = "0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + let act_two = >::from_hex(hex).unwrap().to_vec(); assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err()); } @@ -666,15 +688,18 @@ mod tests { // transport-initiator act2 bad MAC test let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let act_two = >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec(); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af"; + let act_two = >::from_hex(hex).unwrap().to_vec(); assert!(outbound_peer.process_act_two(&act_two[..], &&node_signer).is_err()); } } #[test] fn noise_responder_test_vectors() { - let our_node_id = SecretKey::from_slice(&>::from_hex("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&>::from_hex("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); + let hex = "2121212121212121212121212121212121212121212121212121212121212121"; + let our_node_id = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); + let hex = "2222222222222222222222222222222222222222222222222222222222222222"; + let our_ephemeral = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); let secp_ctx = Secp256k1::new(); let node_signer = TestNodeSigner::new(our_node_id); @@ -689,31 +714,37 @@ mod tests { // transport-responder act1 bad version test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); + let hex = "01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one = >::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); } { // transport-responder act1 bad key serialization test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one =>::from_hex("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); + let hex = "00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one =>::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); } { // transport-responder act1 bad MAC test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec(); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b"; + let act_one = >::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); } { // transport-responder act3 bad version test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one = >::from_hex(hex).unwrap().to_vec(); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); - let act_three = >::from_hex("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); + let hex = "01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; + let act_three = >::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { @@ -724,30 +755,39 @@ mod tests { // transport-responder act3 bad MAC for ciphertext test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one = >::from_hex(hex).unwrap().to_vec(); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); - let act_three = >::from_hex("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); + let hex = "00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; + let act_three = >::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { // transport-responder act3 bad rs test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one = >::from_hex(hex).unwrap().to_vec(); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); - let act_three = >::from_hex("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec(); + let hex = "00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c"; + let act_three = >::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { // transport-responder act3 bad MAC test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); - let act_one = >::from_hex("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; + let act_one = >::from_hex(hex).unwrap().to_vec(); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); - let act_three = >::from_hex("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec(); + let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb"; + let act_three = >::from_hex(hex).unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } } @@ -760,20 +800,27 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); { - let our_node_id = SecretKey::from_slice(&>::from_hex("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); + let hex = "1111111111111111111111111111111111111111111111111111111111111111"; + let our_node_id = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); let node_signer = TestNodeSigner::new(our_node_id); - let act_two = >::from_hex("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], >::from_hex("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); + let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; + let act_two = >::from_hex(hex).unwrap().to_vec(); + let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; + assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], >::from_hex(hex).unwrap()[..]); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, >::from_hex("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); + let hex = "969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9"; + assert_eq!(sk, >::from_hex(hex).unwrap()[..]); assert_eq!(sn, 0); - assert_eq!(sck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, >::from_hex("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); + let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; + assert_eq!(sck, >::from_hex(hex).unwrap()[..]); + let hex = "bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442"; + assert_eq!(rk, >::from_hex(hex).unwrap()[..]); assert_eq!(rn, 0); - assert_eq!(rck, >::from_hex("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); + let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; + assert_eq!(rck, >::from_hex(hex).unwrap()[..]); }, _ => panic!() } @@ -790,17 +837,23 @@ mod tests { assert_eq!(inbound_peer.decrypt_length_header(&len_header[..]).unwrap() as usize, msg.len()); if i == 0 { - assert_eq!(res, >::from_hex("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap()); + let hex = "cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95"; + assert_eq!(res, >::from_hex(hex).unwrap()); } else if i == 1 { - assert_eq!(res, >::from_hex("72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1").unwrap()); + let hex = "72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1"; + assert_eq!(res, >::from_hex(hex).unwrap()); } else if i == 500 { - assert_eq!(res, >::from_hex("178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8").unwrap()); + let hex = "178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8"; + assert_eq!(res, >::from_hex(hex).unwrap()); } else if i == 501 { - assert_eq!(res, >::from_hex("1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd").unwrap()); + let hex = "1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd"; + assert_eq!(res, >::from_hex(hex).unwrap()); } else if i == 1000 { - assert_eq!(res, >::from_hex("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap()); + let hex = "4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09"; + assert_eq!(res, >::from_hex(hex).unwrap()); } else if i == 1001 { - assert_eq!(res, >::from_hex("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap()); + let hex = "2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36"; + assert_eq!(res, >::from_hex(hex).unwrap()); } inbound_peer.decrypt_message(&mut res[2+16..]).unwrap(); From 06cff13b7e54a5d4d15b864c1da8b46d7b8159ad Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 20:25:24 +0000 Subject: [PATCH 06/11] Run rustfmt on `peer_channel_encryptor` --- lightning/src/ln/peer_channel_encryptor.rs | 574 ++++++++++++++------- rustfmt_excluded_files | 1 - 2 files changed, 380 insertions(+), 195 deletions(-) diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index 5d935570595..aebf46f8dd3 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -9,20 +9,20 @@ use crate::prelude::*; -use crate::sign::{NodeSigner, Recipient}; -use crate::ln::msgs::LightningError; use crate::ln::msgs; +use crate::ln::msgs::LightningError; use crate::ln::wire; +use crate::sign::{NodeSigner, Recipient}; -use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hex::DisplayHex; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::{PublicKey,SecretKey}; -use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1; +use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::{PublicKey, SecretKey}; use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC; use crate::crypto::utils::hkdf_extract_expand_twice; @@ -40,13 +40,22 @@ pub const LN_MAX_MSG_LEN: usize = ::core::u16::MAX as usize; // Must be equal to pub const MSG_BUF_ALLOC_SIZE: usize = 2048; // Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256") -const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1]; +const NOISE_CK: [u8; 32] = [ + 0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, + 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1, +]; // Sha256(NOISE_CK || "lightning") -const NOISE_H: [u8; 32] = [0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76]; - -enum NoiseSecretKey<'a, 'b, NS: Deref> where NS::Target: NodeSigner { +const NOISE_H: [u8; 32] = [ + 0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, + 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76, +]; + +enum NoiseSecretKey<'a, 'b, NS: Deref> +where + NS::Target: NodeSigner, +{ InMemory(&'a SecretKey), - NodeSigner(&'b NS) + NodeSigner(&'b NS), } pub enum NextNoiseStep { @@ -73,10 +82,10 @@ enum DirectionalNoiseState { ie: SecretKey, }, Inbound { - ie: Option, // filled in if state >= PostActOne - re: Option, // filled in if state >= PostActTwo + ie: Option, // filled in if state >= PostActOne + re: Option, // filled in if state >= PostActTwo temp_k2: Option<[u8; 32]>, // filled in if state >= PostActTwo - } + }, } enum NoiseState { InProgress { @@ -91,7 +100,7 @@ enum NoiseState { rk: [u8; 32], rn: u64, rck: [u8; 32], - } + }, } pub struct PeerChannelEncryptor { @@ -101,7 +110,9 @@ pub struct PeerChannelEncryptor { } impl PeerChannelEncryptor { - pub fn new_outbound(their_node_id: PublicKey, ephemeral_key: SecretKey) -> PeerChannelEncryptor { + pub fn new_outbound( + their_node_id: PublicKey, ephemeral_key: SecretKey, + ) -> PeerChannelEncryptor { let mut sha = Sha256::engine(); sha.input(&NOISE_H); sha.input(&their_node_id.serialize()[..]); @@ -111,18 +122,16 @@ impl PeerChannelEncryptor { their_node_id: Some(their_node_id), noise_state: NoiseState::InProgress { state: NoiseStep::PreActOne, - directional_state: DirectionalNoiseState::Outbound { - ie: ephemeral_key, - }, - bidirectional_state: BidirectionalNoiseState { - h, - ck: NOISE_CK, - }, - } + directional_state: DirectionalNoiseState::Outbound { ie: ephemeral_key }, + bidirectional_state: BidirectionalNoiseState { h, ck: NOISE_CK }, + }, } } - pub fn new_inbound(node_signer: &NS) -> PeerChannelEncryptor where NS::Target: NodeSigner { + pub fn new_inbound(node_signer: &NS) -> PeerChannelEncryptor + where + NS::Target: NodeSigner, + { let mut sha = Sha256::engine(); sha.input(&NOISE_H); let our_node_id = node_signer.get_node_id(Recipient::Node).unwrap(); @@ -138,16 +147,13 @@ impl PeerChannelEncryptor { re: None, temp_k2: None, }, - bidirectional_state: BidirectionalNoiseState { - h, - ck: NOISE_CK, - }, - } + bidirectional_state: BidirectionalNoiseState { h, ck: NOISE_CK }, + }, } } #[inline] - fn encrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], plaintext: &[u8]) { + fn encrypt_with_ad(res: &mut [u8], n: u64, key: &[u8; 32], h: &[u8], plaintext: &[u8]) { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&n.to_le_bytes()[..]); @@ -160,7 +166,9 @@ impl PeerChannelEncryptor { #[inline] /// Encrypts the message in res[offset..] in-place and pushes a 16-byte tag onto the end of /// res. - fn encrypt_in_place_with_ad(res: &mut Vec, offset: usize, n: u64, key: &[u8; 32], h: &[u8]) { + fn encrypt_in_place_with_ad( + res: &mut Vec, offset: usize, n: u64, key: &[u8; 32], h: &[u8], + ) { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&n.to_le_bytes()[..]); @@ -170,26 +178,43 @@ impl PeerChannelEncryptor { res.extend_from_slice(&tag); } - fn decrypt_in_place_with_ad(inout: &mut [u8], n: u64, key: &[u8; 32], h: &[u8]) -> Result<(), LightningError> { + fn decrypt_in_place_with_ad( + inout: &mut [u8], n: u64, key: &[u8; 32], h: &[u8], + ) -> Result<(), LightningError> { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&n.to_le_bytes()[..]); let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); let (inout, tag) = inout.split_at_mut(inout.len() - 16); if chacha.check_decrypt_in_place(inout, tag).is_err() { - return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); + return Err(LightningError { + err: "Bad MAC".to_owned(), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }); } Ok(()) } #[inline] - fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), LightningError> { + fn decrypt_with_ad( + res: &mut [u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8], + ) -> Result<(), LightningError> { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&n.to_le_bytes()[..]); let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - if chacha.variable_time_decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]).is_err() { - return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); + if chacha + .variable_time_decrypt( + &cyphertext[0..cyphertext.len() - 16], + res, + &cyphertext[cyphertext.len() - 16..], + ) + .is_err() + { + return Err(LightningError { + err: "Bad MAC".to_owned(), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }); } Ok(()) } @@ -202,7 +227,10 @@ impl PeerChannelEncryptor { } #[inline] - fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) { + fn outbound_noise_act( + secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, + their_key: &PublicKey, + ) -> ([u8; 50], [u8; 32]) { let our_pub = PublicKey::from_secret_key(secp_ctx, &our_key); let mut sha = Sha256::engine(); @@ -227,16 +255,27 @@ impl PeerChannelEncryptor { #[inline] fn inbound_noise_act<'a, 'b, NS: Deref>( - state: &mut BidirectionalNoiseState, act: &[u8], secret_key: NoiseSecretKey<'a, 'b, NS> - ) -> Result<(PublicKey, [u8; 32]), LightningError> where NS::Target: NodeSigner { + state: &mut BidirectionalNoiseState, act: &[u8], secret_key: NoiseSecretKey<'a, 'b, NS>, + ) -> Result<(PublicKey, [u8; 32]), LightningError> + where + NS::Target: NodeSigner, + { assert_eq!(act.len(), 50); if act[0] != 0 { - return Err(LightningError{err: format!("Unknown handshake version number {}", act[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); + return Err(LightningError { + err: format!("Unknown handshake version number {}", act[0]), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }); } let their_pub = match PublicKey::from_slice(&act[1..34]) { - Err(_) => return Err(LightningError{err: format!("Invalid public key {}", &act[1..34].as_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}), + Err(_) => { + return Err(LightningError { + err: format!("Invalid public key {}", &act[1..34].as_hex()), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }) + }, Ok(key) => key, }; @@ -247,12 +286,12 @@ impl PeerChannelEncryptor { let ss = match secret_key { NoiseSecretKey::InMemory(secret_key) => SharedSecret::new(&their_pub, secret_key), - NoiseSecretKey::NodeSigner(node_signer) => node_signer - .ecdh(Recipient::Node, &their_pub, None) - .map_err(|_| LightningError { + NoiseSecretKey::NodeSigner(node_signer) => { + node_signer.ecdh(Recipient::Node, &their_pub, None).map_err(|_| LightningError { err: "Failed to derive shared secret".to_owned(), - action: msgs::ErrorAction::DisconnectPeer { msg: None } - })?, + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + })? + }, }; let temp_k = PeerChannelEncryptor::hkdf(state, ss); @@ -269,108 +308,149 @@ impl PeerChannelEncryptor { pub fn get_act_one(&mut self, secp_ctx: &Secp256k1) -> [u8; 50] { match self.noise_state { - NoiseState::InProgress { ref mut state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Outbound { ref ie } => { - if *state != NoiseStep::PreActOne { - panic!("Requested act at wrong step"); - } - - let (res, _) = PeerChannelEncryptor::outbound_noise_act(secp_ctx, bidirectional_state, &ie, &self.their_node_id.unwrap()); - *state = NoiseStep::PostActOne; - res - }, - _ => panic!("Wrong direction for act"), + NoiseState::InProgress { + ref mut state, + ref directional_state, + ref mut bidirectional_state, + } => match directional_state { + &DirectionalNoiseState::Outbound { ref ie } => { + if *state != NoiseStep::PreActOne { + panic!("Requested act at wrong step"); + } + + let (res, _) = PeerChannelEncryptor::outbound_noise_act( + secp_ctx, + bidirectional_state, + &ie, + &self.their_node_id.unwrap(), + ); + *state = NoiseStep::PostActOne; + res }, + _ => panic!("Wrong direction for act"), + }, _ => panic!("Cannot get act one after noise handshake completes"), } } pub fn process_act_one_with_keys( - &mut self, act_one: &[u8], node_signer: &NS, our_ephemeral: SecretKey, secp_ctx: &Secp256k1) - -> Result<[u8; 50], LightningError> where NS::Target: NodeSigner { + &mut self, act_one: &[u8], node_signer: &NS, our_ephemeral: SecretKey, + secp_ctx: &Secp256k1, + ) -> Result<[u8; 50], LightningError> + where + NS::Target: NodeSigner, + { assert_eq!(act_one.len(), 50); match self.noise_state { - NoiseState::InProgress { ref mut state, ref mut directional_state, ref mut bidirectional_state } => - match directional_state { - &mut DirectionalNoiseState::Inbound { ref mut ie, ref mut re, ref mut temp_k2 } => { - if *state != NoiseStep::PreActOne { - panic!("Requested act at wrong step"); - } - - let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, NoiseSecretKey::NodeSigner(node_signer))?; - ie.get_or_insert(their_pub); - - re.get_or_insert(our_ephemeral); - - let (res, temp_k) = - PeerChannelEncryptor::outbound_noise_act(secp_ctx, bidirectional_state, &re.unwrap(), &ie.unwrap()); - *temp_k2 = Some(temp_k); - *state = NoiseStep::PostActTwo; - Ok(res) - }, - _ => panic!("Wrong direction for act"), + NoiseState::InProgress { + ref mut state, + ref mut directional_state, + ref mut bidirectional_state, + } => match directional_state { + &mut DirectionalNoiseState::Inbound { ref mut ie, ref mut re, ref mut temp_k2 } => { + if *state != NoiseStep::PreActOne { + panic!("Requested act at wrong step"); + } + + let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act( + bidirectional_state, + act_one, + NoiseSecretKey::NodeSigner(node_signer), + )?; + ie.get_or_insert(their_pub); + + re.get_or_insert(our_ephemeral); + + let (res, temp_k) = PeerChannelEncryptor::outbound_noise_act( + secp_ctx, + bidirectional_state, + &re.unwrap(), + &ie.unwrap(), + ); + *temp_k2 = Some(temp_k); + *state = NoiseStep::PostActTwo; + Ok(res) }, + _ => panic!("Wrong direction for act"), + }, _ => panic!("Cannot get act one after noise handshake completes"), } } pub fn process_act_two( - &mut self, act_two: &[u8], node_signer: &NS) - -> Result<([u8; 66], PublicKey), LightningError> where NS::Target: NodeSigner { + &mut self, act_two: &[u8], node_signer: &NS, + ) -> Result<([u8; 66], PublicKey), LightningError> + where + NS::Target: NodeSigner, + { assert_eq!(act_two.len(), 50); let final_hkdf; let ck; let res: [u8; 66] = match self.noise_state { - NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Outbound { ref ie } => { - if *state != NoiseStep::PostActOne { - panic!("Requested act at wrong step"); - } - - let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, NoiseSecretKey::::InMemory(&ie))?; - - let mut res = [0; 66]; - let our_node_id = node_signer.get_node_id(Recipient::Node).map_err(|_| LightningError { + NoiseState::InProgress { + ref state, + ref directional_state, + ref mut bidirectional_state, + } => match directional_state { + &DirectionalNoiseState::Outbound { ref ie } => { + if *state != NoiseStep::PostActOne { + panic!("Requested act at wrong step"); + } + + let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act( + bidirectional_state, + act_two, + NoiseSecretKey::::InMemory(&ie), + )?; + + let mut res = [0; 66]; + let our_node_id = + node_signer.get_node_id(Recipient::Node).map_err(|_| LightningError { err: "Failed to encrypt message".to_owned(), - action: msgs::ErrorAction::DisconnectPeer { msg: None } + action: msgs::ErrorAction::DisconnectPeer { msg: None }, })?; - PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]); - - let mut sha = Sha256::engine(); - sha.input(&bidirectional_state.h); - sha.input(&res[1..50]); - bidirectional_state.h = Sha256::from_engine(sha).to_byte_array(); - - let ss = node_signer.ecdh(Recipient::Node, &re, None).map_err(|_| LightningError { + PeerChannelEncryptor::encrypt_with_ad( + &mut res[1..50], + 1, + &temp_k2, + &bidirectional_state.h, + &our_node_id.serialize()[..], + ); + + let mut sha = Sha256::engine(); + sha.input(&bidirectional_state.h); + sha.input(&res[1..50]); + bidirectional_state.h = Sha256::from_engine(sha).to_byte_array(); + + let ss = node_signer.ecdh(Recipient::Node, &re, None).map_err(|_| { + LightningError { err: "Failed to derive shared secret".to_owned(), - action: msgs::ErrorAction::DisconnectPeer { msg: None } - })?; - let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); - - PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]); - final_hkdf = hkdf_extract_expand_twice(&bidirectional_state.ck, &[0; 0]); - ck = bidirectional_state.ck.clone(); - res - }, - _ => panic!("Wrong direction for act"), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + } + })?; + let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); + + PeerChannelEncryptor::encrypt_with_ad( + &mut res[50..], + 0, + &temp_k, + &bidirectional_state.h, + &[0; 0], + ); + final_hkdf = hkdf_extract_expand_twice(&bidirectional_state.ck, &[0; 0]); + ck = bidirectional_state.ck.clone(); + res }, + _ => panic!("Wrong direction for act"), + }, _ => panic!("Cannot get act one after noise handshake completes"), }; let (sk, rk) = final_hkdf; - self.noise_state = NoiseState::Finished { - sk, - sn: 0, - sck: ck.clone(), - rk, - rn: 0, - rck: ck, - }; + self.noise_state = NoiseState::Finished { sk, sn: 0, sck: ck.clone(), rk, rn: 0, rck: ck }; Ok((res, self.their_node_id.unwrap().clone())) } @@ -381,49 +461,65 @@ impl PeerChannelEncryptor { let final_hkdf; let ck; match self.noise_state { - NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Inbound { ie: _, ref re, ref temp_k2 } => { - if *state != NoiseStep::PostActTwo { - panic!("Requested act at wrong step"); - } - if act_three[0] != 0 { - return Err(LightningError{err: format!("Unknown handshake version number {}", act_three[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - - let mut their_node_id = [0; 33]; - PeerChannelEncryptor::decrypt_with_ad(&mut their_node_id, 1, &temp_k2.unwrap(), &bidirectional_state.h, &act_three[1..50])?; - self.their_node_id = Some(match PublicKey::from_slice(&their_node_id) { - Ok(key) => key, - Err(_) => return Err(LightningError{err: format!("Bad node_id from peer, {}", &their_node_id.as_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}), + NoiseState::InProgress { + ref state, + ref directional_state, + ref mut bidirectional_state, + } => match directional_state { + &DirectionalNoiseState::Inbound { ie: _, ref re, ref temp_k2 } => { + if *state != NoiseStep::PostActTwo { + panic!("Requested act at wrong step"); + } + if act_three[0] != 0 { + return Err(LightningError { + err: format!("Unknown handshake version number {}", act_three[0]), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, }); - - let mut sha = Sha256::engine(); - sha.input(&bidirectional_state.h); - sha.input(&act_three[1..50]); - bidirectional_state.h = Sha256::from_engine(sha).to_byte_array(); - - let ss = SharedSecret::new(&self.their_node_id.unwrap(), &re.unwrap()); - let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); - - PeerChannelEncryptor::decrypt_with_ad(&mut [0; 0], 0, &temp_k, &bidirectional_state.h, &act_three[50..])?; - final_hkdf = hkdf_extract_expand_twice(&bidirectional_state.ck, &[0; 0]); - ck = bidirectional_state.ck.clone(); - }, - _ => panic!("Wrong direction for act"), + } + + let mut their_node_id = [0; 33]; + PeerChannelEncryptor::decrypt_with_ad( + &mut their_node_id, + 1, + &temp_k2.unwrap(), + &bidirectional_state.h, + &act_three[1..50], + )?; + self.their_node_id = Some(match PublicKey::from_slice(&their_node_id) { + Ok(key) => key, + Err(_) => { + return Err(LightningError { + err: format!("Bad node_id from peer, {}", &their_node_id.as_hex()), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }) + }, + }); + + let mut sha = Sha256::engine(); + sha.input(&bidirectional_state.h); + sha.input(&act_three[1..50]); + bidirectional_state.h = Sha256::from_engine(sha).to_byte_array(); + + let ss = SharedSecret::new(&self.their_node_id.unwrap(), &re.unwrap()); + let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); + + PeerChannelEncryptor::decrypt_with_ad( + &mut [0; 0], + 0, + &temp_k, + &bidirectional_state.h, + &act_three[50..], + )?; + final_hkdf = hkdf_extract_expand_twice(&bidirectional_state.ck, &[0; 0]); + ck = bidirectional_state.ck.clone(); }, + _ => panic!("Wrong direction for act"), + }, _ => panic!("Cannot get act one after noise handshake completes"), } let (rk, sk) = final_hkdf; - self.noise_state = NoiseState::Finished { - sk, - sn: 0, - sck: ck.clone(), - rk, - rn: 0, - rck: ck, - }; + self.noise_state = NoiseState::Finished { sk, sn: 0, sck: ck.clone(), rk, rn: 0, rck: ck }; Ok(self.their_node_id.unwrap().clone()) } @@ -451,10 +547,16 @@ impl PeerChannelEncryptor { *sn = 0; } - Self::encrypt_with_ad(&mut msgbuf[0..16+2], *sn, sk, &[0; 0], &(msg_len as u16).to_be_bytes()); + Self::encrypt_with_ad( + &mut msgbuf[0..16 + 2], + *sn, + sk, + &[0; 0], + &(msg_len as u16).to_be_bytes(), + ); *sn += 1; - Self::encrypt_in_place_with_ad(msgbuf, 16+2, *sn, sk, &[0; 0]); + Self::encrypt_in_place_with_ad(msgbuf, 16 + 2, *sn, sk, &[0; 0]); *sn += 1; }, _ => panic!("Tried to encrypt a message prior to noise handshake completion"), @@ -485,7 +587,7 @@ impl PeerChannelEncryptor { /// Decrypts a message length header from the remote peer. /// panics if noise handshake has not yet finished or msg.len() != 18 pub fn decrypt_length_header(&mut self, msg: &[u8]) -> Result { - assert_eq!(msg.len(), 16+2); + assert_eq!(msg.len(), 16 + 2); match self.noise_state { NoiseState::Finished { sk: _, sn: _, sck: _, ref mut rk, ref mut rn, ref mut rck } => { @@ -526,21 +628,19 @@ impl PeerChannelEncryptor { pub fn get_noise_step(&self) -> NextNoiseStep { match self.noise_state { - NoiseState::InProgress {ref state, ..} => { - match state { - &NoiseStep::PreActOne => NextNoiseStep::ActOne, - &NoiseStep::PostActOne => NextNoiseStep::ActTwo, - &NoiseStep::PostActTwo => NextNoiseStep::ActThree, - } + NoiseState::InProgress { ref state, .. } => match state { + &NoiseStep::PreActOne => NextNoiseStep::ActOne, + &NoiseStep::PostActOne => NextNoiseStep::ActTwo, + &NoiseStep::PostActTwo => NextNoiseStep::ActThree, }, - NoiseState::Finished {..} => NextNoiseStep::NoiseComplete, + NoiseState::Finished { .. } => NextNoiseStep::NoiseComplete, } } pub fn is_ready_for_encryption(&self) -> bool { match self.noise_state { - NoiseState::InProgress {..} => { false }, - NoiseState::Finished {..} => { true } + NoiseState::InProgress { .. } => false, + NoiseState::Finished { .. } => true, } } } @@ -559,7 +659,7 @@ impl MessageBuf { } // In addition to the message (continaing the two message type bytes), we also have to add // the message length header (and its MAC) and the message MAC. - let mut res = Vec::with_capacity(encoded_msg.len() + 16*2 + 2); + let mut res = Vec::with_capacity(encoded_msg.len() + 16 * 2 + 2); res.resize(encoded_msg.len() + 16 + 2, 0); res[16 + 2..].copy_from_slice(&encoded_msg); Self(res) @@ -571,10 +671,10 @@ mod tests { use super::{MessageBuf, LN_MAX_MSG_LEN}; use bitcoin::hex::FromHex; - use bitcoin::secp256k1::{PublicKey, SecretKey}; use bitcoin::secp256k1::Secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; - use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState}; + use crate::ln::peer_channel_encryptor::{NoiseState, PeerChannelEncryptor}; use crate::util::test_utils::TestNodeSigner; fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor { @@ -583,7 +683,10 @@ mod tests { let secp_ctx = Secp256k1::signing_only(); let hex = "1212121212121212121212121212121212121212121212121212121212121212"; - let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap()); + let mut outbound_peer = PeerChannelEncryptor::new_outbound( + their_node_id, + SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(), + ); let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; assert_eq!(outbound_peer.get_act_one(&secp_ctx)[..], >::from_hex(hex).unwrap()[..]); outbound_peer @@ -603,14 +706,27 @@ mod tests { let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; let act_one = >::from_hex(hex).unwrap().to_vec(); let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .unwrap()[..], + >::from_hex(hex).unwrap()[..] + ); let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; let act_three = >::from_hex(hex).unwrap().to_vec(); // test vector doesn't specify the initiator static key, but it's the same as the one // from transport-initiator successful handshake let hex = "034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"; - assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], + >::from_hex(hex).unwrap()[..] + ); match inbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { @@ -625,7 +741,7 @@ mod tests { let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; assert_eq!(rck, >::from_hex(hex).unwrap()[..]); }, - _ => panic!() + _ => panic!(), } inbound_peer @@ -644,7 +760,10 @@ mod tests { let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; let act_two = >::from_hex(hex).unwrap().to_vec(); let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; - assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], + >::from_hex(hex).unwrap()[..] + ); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { @@ -659,7 +778,7 @@ mod tests { let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; assert_eq!(rck, >::from_hex(hex).unwrap()[..]); }, - _ => panic!() + _ => panic!(), } } { @@ -716,15 +835,29 @@ mod tests { let hex = "01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; let act_one = >::from_hex(hex).unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); + assert!(inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .is_err()); } { // transport-responder act1 bad key serialization test let mut inbound_peer = PeerChannelEncryptor::new_inbound(&&node_signer); let hex = "00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; - let act_one =>::from_hex(hex).unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); + let act_one = >::from_hex(hex).unwrap().to_vec(); + assert!(inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .is_err()); } { // transport-responder act1 bad MAC test @@ -732,7 +865,14 @@ mod tests { let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b"; let act_one = >::from_hex(hex).unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).is_err()); + assert!(inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .is_err()); } { // transport-responder act3 bad version test @@ -741,7 +881,17 @@ mod tests { let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; let act_one = >::from_hex(hex).unwrap().to_vec(); let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .unwrap()[..], + >::from_hex(hex).unwrap()[..] + ); let hex = "01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; let act_three = >::from_hex(hex).unwrap().to_vec(); @@ -758,7 +908,17 @@ mod tests { let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; let act_one = >::from_hex(hex).unwrap().to_vec(); let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .unwrap()[..], + >::from_hex(hex).unwrap()[..] + ); let hex = "00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; let act_three = >::from_hex(hex).unwrap().to_vec(); @@ -771,7 +931,17 @@ mod tests { let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; let act_one = >::from_hex(hex).unwrap().to_vec(); let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .unwrap()[..], + >::from_hex(hex).unwrap()[..] + ); let hex = "00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c"; let act_three = >::from_hex(hex).unwrap().to_vec(); @@ -784,7 +954,17 @@ mod tests { let hex = "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"; let act_one = >::from_hex(hex).unwrap().to_vec(); let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &&node_signer, our_ephemeral.clone(), &secp_ctx).unwrap()[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + inbound_peer + .process_act_one_with_keys( + &act_one[..], + &&node_signer, + our_ephemeral.clone(), + &secp_ctx + ) + .unwrap()[..], + >::from_hex(hex).unwrap()[..] + ); let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb"; let act_three = >::from_hex(hex).unwrap().to_vec(); @@ -792,7 +972,6 @@ mod tests { } } - #[test] fn message_encryption_decryption_test_vectors() { // We use the same keys as the initiator and responder test vectors, so we copy those tests @@ -801,13 +980,17 @@ mod tests { { let hex = "1111111111111111111111111111111111111111111111111111111111111111"; - let our_node_id = SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); + let our_node_id = + SecretKey::from_slice(&>::from_hex(hex).unwrap()[..]).unwrap(); let node_signer = TestNodeSigner::new(our_node_id); let hex = "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"; let act_two = >::from_hex(hex).unwrap().to_vec(); let hex = "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"; - assert_eq!(outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], >::from_hex(hex).unwrap()[..]); + assert_eq!( + outbound_peer.process_act_two(&act_two[..], &&node_signer).unwrap().0[..], + >::from_hex(hex).unwrap()[..] + ); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { @@ -822,7 +1005,7 @@ mod tests { let hex = "919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01"; assert_eq!(rck, >::from_hex(hex).unwrap()[..]); }, - _ => panic!() + _ => panic!(), } } @@ -831,10 +1014,13 @@ mod tests { for i in 0..1005 { let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f]; let mut res = outbound_peer.encrypt_buffer(MessageBuf::from_encoded(&msg)); - assert_eq!(res.len(), 5 + 2*16 + 2); + assert_eq!(res.len(), 5 + 2 * 16 + 2); - let len_header = res[0..2+16].to_vec(); - assert_eq!(inbound_peer.decrypt_length_header(&len_header[..]).unwrap() as usize, msg.len()); + let len_header = res[0..2 + 16].to_vec(); + assert_eq!( + inbound_peer.decrypt_length_header(&len_header[..]).unwrap() as usize, + msg.len() + ); if i == 0 { let hex = "cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95"; @@ -856,7 +1042,7 @@ mod tests { assert_eq!(res, >::from_hex(hex).unwrap()); } - inbound_peer.decrypt_message(&mut res[2+16..]).unwrap(); + inbound_peer.decrypt_message(&mut res[2 + 16..]).unwrap(); assert_eq!(res[2 + 16..res.len() - 16], msg[..]); } } diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index fa7c8ced96f..af1bb4a57fa 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -26,7 +26,6 @@ lightning/src/ln/onion_payment.rs lightning/src/ln/onion_route_tests.rs lightning/src/ln/outbound_payment.rs lightning/src/ln/payment_tests.rs -lightning/src/ln/peer_channel_encryptor.rs lightning/src/ln/peer_handler.rs lightning/src/ln/priv_short_conf_tests.rs lightning/src/ln/reload_tests.rs From 6cecdebb52ea7b15c6cabb6f2caf22a788e132fa Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 20:26:31 +0000 Subject: [PATCH 07/11] Clean up some nits in `peer_channel_encryptor` --- lightning/src/ln/peer_channel_encryptor.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index aebf46f8dd3..3927b2f0ba7 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -203,20 +203,13 @@ impl PeerChannelEncryptor { nonce[4..].copy_from_slice(&n.to_le_bytes()[..]); let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - if chacha - .variable_time_decrypt( - &cyphertext[0..cyphertext.len() - 16], - res, - &cyphertext[cyphertext.len() - 16..], - ) - .is_err() - { - return Err(LightningError { - err: "Bad MAC".to_owned(), - action: msgs::ErrorAction::DisconnectPeer { msg: None }, - }); - } - Ok(()) + let hmac = &cyphertext[cyphertext.len() - 16..]; + let mac_check = + chacha.variable_time_decrypt(&cyphertext[0..cyphertext.len() - 16], res, hmac); + mac_check.map_err(|()| LightningError { + err: "Bad MAC".to_owned(), + action: msgs::ErrorAction::DisconnectPeer { msg: None }, + }) } #[inline] From 0daf48a674cc8318982017e2b0108c3ca92d5a64 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 2 May 2025 20:44:39 +0000 Subject: [PATCH 08/11] f pce split rather than slice --- lightning/src/ln/peer_channel_encryptor.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index 3927b2f0ba7..310308805ec 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -202,10 +202,9 @@ impl PeerChannelEncryptor { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&n.to_le_bytes()[..]); - let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - let hmac = &cyphertext[cyphertext.len() - 16..]; + let (data, hmac) = cyphertext.split_at(cyphertext.len() - 16); let mac_check = - chacha.variable_time_decrypt(&cyphertext[0..cyphertext.len() - 16], res, hmac); + ChaCha20Poly1305RFC::new(key, &nonce, h).variable_time_decrypt(&data, res, hmac); mac_check.map_err(|()| LightningError { err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer { msg: None }, From 1883f7916243c1b8a8fbe14badf2e9dfbdd3c65c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 21:05:13 +0000 Subject: [PATCH 09/11] Run `rustfmt` on `invoice_utils.rs` --- lightning/src/ln/invoice_utils.rs | 933 +++++++++++++++++++++--------- rustfmt_excluded_files | 1 - 2 files changed, 651 insertions(+), 283 deletions(-) diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index a3ee6dec517..a33f5b788ec 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -1,25 +1,29 @@ //! Convenient utilities to create an invoice. -use lightning_invoice::{Bolt11Invoice, CreationError, Currency, InvoiceBuilder, SignOrCreationError}; -use lightning_invoice::{Description, Bolt11InvoiceDescription, Sha256}; +use lightning_invoice::{ + Bolt11Invoice, CreationError, Currency, InvoiceBuilder, SignOrCreationError, +}; +use lightning_invoice::{Bolt11InvoiceDescription, Description, Sha256}; use crate::prelude::*; -use bitcoin::hashes::Hash; -use crate::sign::{Recipient, NodeSigner, EntropySource}; -use crate::types::payment::PaymentHash; use crate::ln::channel_state::ChannelDetails; -use crate::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA, MIN_FINAL_CLTV_EXPIRY_DELTA}; +use crate::ln::channelmanager::{ + PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA, MIN_FINAL_CLTV_EXPIRY_DELTA, +}; use crate::ln::inbound_payment::{create, create_from_hash}; use crate::routing::gossip::RoutingFees; use crate::routing::router::{RouteHint, RouteHintHop}; +use crate::sign::{EntropySource, NodeSigner, Recipient}; +use crate::types::payment::PaymentHash; use crate::util::logger::{Logger, Record}; -use bitcoin::secp256k1::PublicKey; use alloc::collections::{btree_map, BTreeMap}; -use core::ops::Deref; -use core::time::Duration; +use bitcoin::hashes::Hash; +use bitcoin::secp256k1::PublicKey; #[cfg(not(feature = "std"))] use core::iter::Iterator; +use core::ops::Deref; +use core::time::Duration; /// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice." /// See [`PhantomKeysManager`] for more information on phantom node payments. @@ -59,11 +63,15 @@ use core::iter::Iterator; /// [`PhantomRouteHints::channels`]: crate::ln::channelmanager::PhantomRouteHints::channels /// [`MIN_FINAL_CLTV_EXPIRY_DETLA`]: crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA #[cfg_attr(feature = "std", doc = "")] -#[cfg_attr(feature = "std", doc = "This can be used in a `no_std` environment, where [`std::time::SystemTime`] is not available and the current time is supplied by the caller.")] +#[cfg_attr( + feature = "std", + doc = "This can be used in a `no_std` environment, where [`std::time::SystemTime`] is not available and the current time is supplied by the caller." +)] pub fn create_phantom_invoice( amt_msat: Option, payment_hash: Option, description: String, - invoice_expiry_delta_secs: u32, phantom_route_hints: Vec, entropy_source: ES, - node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option, duration_since_epoch: Duration, + invoice_expiry_delta_secs: u32, phantom_route_hints: Vec, + entropy_source: ES, node_signer: NS, logger: L, network: Currency, + min_final_cltv_expiry_delta: Option, duration_since_epoch: Duration, ) -> Result> where ES::Target: EntropySource, @@ -73,8 +81,17 @@ where let description = Description::new(description).map_err(SignOrCreationError::CreationError)?; let description = Bolt11InvoiceDescription::Direct(description); _create_phantom_invoice::( - amt_msat, payment_hash, description, invoice_expiry_delta_secs, phantom_route_hints, - entropy_source, node_signer, logger, network, min_final_cltv_expiry_delta, duration_since_epoch, + amt_msat, + payment_hash, + description, + invoice_expiry_delta_secs, + phantom_route_hints, + entropy_source, + node_signer, + logger, + network, + min_final_cltv_expiry_delta, + duration_since_epoch, ) } @@ -114,11 +131,15 @@ where /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash /// [`PhantomRouteHints::channels`]: crate::ln::channelmanager::PhantomRouteHints::channels #[cfg_attr(feature = "std", doc = "")] -#[cfg_attr(feature = "std", doc = "This version can be used in a `no_std` environment, where [`std::time::SystemTime`] is not available and the current time is supplied by the caller.")] +#[cfg_attr( + feature = "std", + doc = "This version can be used in a `no_std` environment, where [`std::time::SystemTime`] is not available and the current time is supplied by the caller." +)] pub fn create_phantom_invoice_with_description_hash( amt_msat: Option, payment_hash: Option, invoice_expiry_delta_secs: u32, description_hash: Sha256, phantom_route_hints: Vec, entropy_source: ES, - node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option, duration_since_epoch: Duration, + node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option, + duration_since_epoch: Duration, ) -> Result> where ES::Target: EntropySource, @@ -126,40 +147,52 @@ where L::Target: Logger, { _create_phantom_invoice::( - amt_msat, payment_hash, Bolt11InvoiceDescription::Hash(description_hash), - invoice_expiry_delta_secs, phantom_route_hints, entropy_source, node_signer, logger, network, - min_final_cltv_expiry_delta, duration_since_epoch, + amt_msat, + payment_hash, + Bolt11InvoiceDescription::Hash(description_hash), + invoice_expiry_delta_secs, + phantom_route_hints, + entropy_source, + node_signer, + logger, + network, + min_final_cltv_expiry_delta, + duration_since_epoch, ) } const MAX_CHANNEL_HINTS: usize = 3; fn _create_phantom_invoice( - amt_msat: Option, payment_hash: Option, description: Bolt11InvoiceDescription, - invoice_expiry_delta_secs: u32, phantom_route_hints: Vec, entropy_source: ES, - node_signer: NS, logger: L, network: Currency, min_final_cltv_expiry_delta: Option, duration_since_epoch: Duration, + amt_msat: Option, payment_hash: Option, + description: Bolt11InvoiceDescription, invoice_expiry_delta_secs: u32, + phantom_route_hints: Vec, entropy_source: ES, node_signer: NS, logger: L, + network: Currency, min_final_cltv_expiry_delta: Option, duration_since_epoch: Duration, ) -> Result> where ES::Target: EntropySource, NS::Target: NodeSigner, L::Target: Logger, { - if phantom_route_hints.is_empty() { - return Err(SignOrCreationError::CreationError( - CreationError::MissingRouteHints, - )); + return Err(SignOrCreationError::CreationError(CreationError::MissingRouteHints)); } - if min_final_cltv_expiry_delta.is_some() && min_final_cltv_expiry_delta.unwrap().saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA { - return Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort)); + if min_final_cltv_expiry_delta.is_some() + && min_final_cltv_expiry_delta.unwrap().saturating_add(3) < MIN_FINAL_CLTV_EXPIRY_DELTA + { + return Err(SignOrCreationError::CreationError( + CreationError::MinFinalCltvExpiryDeltaTooShort, + )); } let invoice = match description { Bolt11InvoiceDescription::Direct(description) => { InvoiceBuilder::new(network).description(description.into_inner().0) - } - Bolt11InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0), + }, + Bolt11InvoiceDescription::Hash(hash) => { + InvoiceBuilder::new(network).description_hash(hash.0) + }, }; let keys = node_signer.get_inbound_payment_key(); @@ -169,8 +202,7 @@ where amt_msat, payment_hash, invoice_expiry_delta_secs, - duration_since_epoch - .as_secs(), + duration_since_epoch.as_secs(), min_final_cltv_expiry_delta, ) .map_err(|_| SignOrCreationError::CreationError(CreationError::InvalidAmount))?; @@ -181,15 +213,18 @@ where amt_msat, invoice_expiry_delta_secs, &entropy_source, - duration_since_epoch - .as_secs(), + duration_since_epoch.as_secs(), min_final_cltv_expiry_delta, ) .map_err(|_| SignOrCreationError::CreationError(CreationError::InvalidAmount))? }; - log_trace!(logger, "Creating phantom invoice from {} participating nodes with payment hash {}", - phantom_route_hints.len(), &payment_hash); + log_trace!( + logger, + "Creating phantom invoice from {} participating nodes with payment hash {}", + phantom_route_hints.len(), + &payment_hash + ); let mut invoice = invoice .duration_since_epoch(duration_since_epoch) @@ -197,26 +232,31 @@ where .payment_secret(payment_secret) .min_final_cltv_expiry_delta( // Add a buffer of 3 to the delta if present, otherwise use LDK's minimum. - min_final_cltv_expiry_delta.map(|x| x.saturating_add(3)).unwrap_or(MIN_FINAL_CLTV_EXPIRY_DELTA).into()) + min_final_cltv_expiry_delta + .map(|x| x.saturating_add(3)) + .unwrap_or(MIN_FINAL_CLTV_EXPIRY_DELTA) + .into(), + ) .expiry_time(Duration::from_secs(invoice_expiry_delta_secs.into())); if let Some(amt) = amt_msat { invoice = invoice.amount_milli_satoshis(amt); } - - for route_hint in select_phantom_hints(amt_msat, phantom_route_hints, logger).take(MAX_CHANNEL_HINTS) { + for route_hint in + select_phantom_hints(amt_msat, phantom_route_hints, logger).take(MAX_CHANNEL_HINTS) + { invoice = invoice.private_route(route_hint); } let raw_invoice = match invoice.build_raw() { Ok(inv) => inv, - Err(e) => return Err(SignOrCreationError::CreationError(e)) + Err(e) => return Err(SignOrCreationError::CreationError(e)), }; let signature = node_signer.sign_invoice(&raw_invoice, Recipient::PhantomNode); let signed_raw_invoice = raw_invoice.sign(|_| signature); match signed_raw_invoice { Ok(inv) => Ok(Bolt11Invoice::from_signed(inv).unwrap()), - Err(e) => Err(SignOrCreationError::SignError(e)) + Err(e) => Err(SignOrCreationError::SignError(e)), } } @@ -228,16 +268,20 @@ where /// * Select one hint from each node, up to three hints or until we run out of hints. /// /// [`PhantomKeysManager`]: crate::sign::PhantomKeysManager -fn select_phantom_hints(amt_msat: Option, phantom_route_hints: Vec, - logger: L) -> impl Iterator +fn select_phantom_hints( + amt_msat: Option, phantom_route_hints: Vec, logger: L, +) -> impl Iterator where L::Target: Logger, { let mut phantom_hints: Vec<_> = Vec::new(); for PhantomRouteHints { channels, phantom_scid, real_node_pubkey } in phantom_route_hints { - log_trace!(logger, "Generating phantom route hints for node {}", - log_pubkey!(real_node_pubkey)); + log_trace!( + logger, + "Generating phantom route hints for node {}", + log_pubkey!(real_node_pubkey) + ); let route_hints = sort_and_filter_channels(channels, amt_msat, &logger); // If we have any public channel, the route hints from `sort_and_filter_channels` will be @@ -261,10 +305,7 @@ where hint.0.push(RouteHintHop { src_node_id: real_node_pubkey, short_channel_id: phantom_scid, - fees: RoutingFees { - base_msat: 0, - proportional_millionths: 0, - }, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0 }, cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA, htlc_minimum_msat: None, htlc_maximum_msat: None, @@ -329,9 +370,7 @@ fn rotate_through_iterators>(mut vecs: Vec) -> impl /// * Sorted by lowest inbound capacity if an online channel with the minimum amount requested exists, /// otherwise sort by highest inbound capacity to give the payment the best chance of succeeding. pub(super) fn sort_and_filter_channels( - channels: Vec, - min_inbound_capacity_msat: Option, - logger: &L, + channels: Vec, min_inbound_capacity_msat: Option, logger: &L, ) -> impl ExactSizeIterator where L::Target: Logger, @@ -354,13 +393,16 @@ where }, cltv_expiry_delta: forwarding_info.cltv_expiry_delta, htlc_minimum_msat: channel.inbound_htlc_minimum_msat, - htlc_maximum_msat: channel.inbound_htlc_maximum_msat,}]) + htlc_maximum_msat: channel.inbound_htlc_maximum_msat, + }]) }; log_trace!(logger, "Considering {} channels for invoice route hints", channels.len()); for channel in channels.into_iter().filter(|chan| chan.is_channel_ready) { let logger = WithChannelDetails::from(logger, &channel); - if channel.get_inbound_payment_scid().is_none() || channel.counterparty.forwarding_info.is_none() { + if channel.get_inbound_payment_scid().is_none() + || channel.counterparty.forwarding_info.is_none() + { log_trace!(logger, "Ignoring channel {} for invoice route hints", &channel.channel_id); continue; } @@ -374,15 +416,21 @@ where } else { // If any public channel exists, return no hints and let the sender // look at the public channels instead. - log_trace!(logger, "Not including channels in invoice route hints on account of public channel {}", - &channel.channel_id); + log_trace!( + logger, + "Not including channels in invoice route hints on account of public channel {}", + &channel.channel_id + ); return vec![].into_iter().take(MAX_CHANNEL_HINTS).map(route_hint_from_channel); } } if channel.inbound_capacity_msat >= min_inbound_capacity { if !min_capacity_channel_exists { - log_trace!(logger, "Channel with enough inbound capacity exists for invoice route hints"); + log_trace!( + logger, + "Channel with enough inbound capacity exists for invoice route hints" + ); min_capacity_channel_exists = true; } @@ -404,12 +452,16 @@ where let new_now_public = channel.is_announced && !entry.get().is_announced; // Decide whether we prefer the currently selected channel with the node to the new one, // based on their inbound capacity. - let prefer_current = prefer_current_channel(min_inbound_capacity_msat, current_max_capacity, - channel.inbound_capacity_msat); + let prefer_current = prefer_current_channel( + min_inbound_capacity_msat, + current_max_capacity, + channel.inbound_capacity_msat, + ); // If the public-ness of the channel has not changed (in which case simply defer to // `new_now_public), and this channel has more desirable inbound than the incumbent, // prefer to include this channel. - let new_channel_preferable = channel.is_announced == entry.get().is_announced && !prefer_current; + let new_channel_preferable = + channel.is_announced == entry.get().is_announced && !prefer_current; if new_now_public || new_channel_preferable { log_trace!(logger, @@ -429,10 +481,10 @@ where &channel.channel_id, channel.short_channel_id, channel.inbound_capacity_msat); } - } + }, btree_map::Entry::Vacant(entry) => { entry.insert(channel); - } + }, } } @@ -462,32 +514,44 @@ where has_enough_capacity } else if online_channel_exists { channel.is_usable - } else { true }; + } else { + true + }; if include_channel { - log_trace!(logger, "Including channel {} in invoice route hints", - &channel.channel_id); + log_trace!( + logger, + "Including channel {} in invoice route hints", + &channel.channel_id + ); } else if !has_enough_capacity { - log_trace!(logger, "Ignoring channel {} without enough capacity for invoice route hints", - &channel.channel_id); + log_trace!( + logger, + "Ignoring channel {} without enough capacity for invoice route hints", + &channel.channel_id + ); } else { debug_assert!(!channel.is_usable || (has_pub_unconf_chan && !channel.is_announced)); - log_trace!(logger, "Ignoring channel {} with disconnected peer", - &channel.channel_id); + log_trace!( + logger, + "Ignoring channel {} with disconnected peer", + &channel.channel_id + ); } include_channel }) .collect::>(); - eligible_channels.sort_unstable_by(|a, b| { - if online_min_capacity_channel_exists { - a.inbound_capacity_msat.cmp(&b.inbound_capacity_msat) - } else { - b.inbound_capacity_msat.cmp(&a.inbound_capacity_msat) - }}); + eligible_channels.sort_unstable_by(|a, b| { + if online_min_capacity_channel_exists { + a.inbound_capacity_msat.cmp(&b.inbound_capacity_msat) + } else { + b.inbound_capacity_msat.cmp(&a.inbound_capacity_msat) + } + }); - eligible_channels.into_iter().take(MAX_CHANNEL_HINTS).map(route_hint_from_channel) + eligible_channels.into_iter().take(MAX_CHANNEL_HINTS).map(route_hint_from_channel) } /// prefer_current_channel chooses a channel to use for route hints between a currently selected and candidate @@ -501,13 +565,13 @@ where /// our change"). /// * If no channel above our minimum amount exists, then we just prefer the channel with the most inbound to give /// payments the best chance of succeeding in multiple parts. -fn prefer_current_channel(min_inbound_capacity_msat: Option, current_channel: u64, - candidate_channel: u64) -> bool { - +fn prefer_current_channel( + min_inbound_capacity_msat: Option, current_channel: u64, candidate_channel: u64, +) -> bool { // If no min amount is given for the hints, err of the side of caution and choose the largest channel inbound to // maximize chances of any payment succeeding. if min_inbound_capacity_msat.is_none() { - return current_channel > candidate_channel + return current_channel > candidate_channel; } let scaled_min_inbound = min_inbound_capacity_msat.unwrap() * 110; @@ -515,25 +579,31 @@ fn prefer_current_channel(min_inbound_capacity_msat: Option, current_channe let candidate_sufficient = candidate_channel * 100 >= scaled_min_inbound; if current_sufficient && candidate_sufficient { - return current_channel < candidate_channel + return current_channel < candidate_channel; } else if current_sufficient { - return true + return true; } else if candidate_sufficient { - return false + return false; } current_channel > candidate_channel } /// Adds relevant context to a [`Record`] before passing it to the wrapped [`Logger`]. -struct WithChannelDetails<'a, 'b, L: Deref> where L::Target: Logger { +struct WithChannelDetails<'a, 'b, L: Deref> +where + L::Target: Logger, +{ /// The logger to delegate to after adding context to the record. logger: &'a L, /// The [`ChannelDetails`] for adding relevant context to the logged record. - details: &'b ChannelDetails + details: &'b ChannelDetails, } -impl<'a, 'b, L: Deref> Logger for WithChannelDetails<'a, 'b, L> where L::Target: Logger { +impl<'a, 'b, L: Deref> Logger for WithChannelDetails<'a, 'b, L> +where + L::Target: Logger, +{ fn log(&self, mut record: Record) { record.peer_id = Some(self.details.counterparty.node_id); record.channel_id = Some(self.details.channel_id); @@ -541,7 +611,10 @@ impl<'a, 'b, L: Deref> Logger for WithChannelDetails<'a, 'b, L> where L::Target: } } -impl<'a, 'b, L: Deref> WithChannelDetails<'a, 'b, L> where L::Target: Logger { +impl<'a, 'b, L: Deref> WithChannelDetails<'a, 'b, L> +where + L::Target: Logger, +{ fn from(logger: &'a L, details: &'b ChannelDetails) -> Self { Self { logger, details } } @@ -550,22 +623,27 @@ impl<'a, 'b, L: Deref> WithChannelDetails<'a, 'b, L> where L::Target: Logger { #[cfg(test)] mod test { use super::*; - use core::time::Duration; - use lightning_invoice::{Currency, Description, Bolt11InvoiceDescriptionRef, SignOrCreationError, CreationError}; - use bitcoin::hashes::{Hash, sha256}; - use bitcoin::hashes::sha256::Hash as Sha256; - use bitcoin::network::Network; - use crate::sign::PhantomKeysManager; use crate::chain::channelmonitor::HTLC_FAIL_BACK_BUFFER; - use crate::types::payment::{PaymentHash, PaymentPreimage}; - use crate::ln::channelmanager::{Bolt11InvoiceParameters, PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY_DELTA, PaymentId, RecipientOnionFields, Retry}; + use crate::ln::channelmanager::{ + Bolt11InvoiceParameters, PaymentId, PhantomRouteHints, RecipientOnionFields, Retry, + MIN_FINAL_CLTV_EXPIRY_DELTA, + }; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent}; use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig}; - use crate::util::test_utils; + use crate::sign::PhantomKeysManager; + use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::config::UserConfig; - use std::collections::HashSet; use crate::util::dyn_signer::{DynKeysInterface, DynPhantomKeysInterface}; + use crate::util::test_utils; + use bitcoin::hashes::sha256::Hash as Sha256; + use bitcoin::hashes::{sha256, Hash}; + use bitcoin::network::Network; + use core::time::Duration; + use lightning_invoice::{ + Bolt11InvoiceDescriptionRef, CreationError, Currency, Description, SignOrCreationError, + }; + use std::collections::HashSet; #[test] fn test_prefer_current_channel() { @@ -594,7 +672,6 @@ mod test { assert_eq!(prefer_current_channel(Some(200), 100, 150), false); } - #[test] fn create_and_pay_for_bolt11_invoice() { let chanmon_cfgs = create_chanmon_cfgs(2); @@ -603,9 +680,8 @@ mod test { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - let description = Bolt11InvoiceDescription::Direct( - Description::new("test".to_string()).unwrap() - ); + let description = + Bolt11InvoiceDescription::Direct(Description::new("test".to_string()).unwrap()); let non_default_invoice_expiry_secs = 4200; let invoice_params = Bolt11InvoiceParameters { amount_msats: Some(10_000), @@ -617,32 +693,52 @@ mod test { assert_eq!(invoice.amount_milli_satoshis(), Some(10_000)); // If no `min_final_cltv_expiry_delta` is specified, then it should be `MIN_FINAL_CLTV_EXPIRY_DELTA`. assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescriptionRef::Direct(&Description::new("test".to_string()).unwrap())); - assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into())); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescriptionRef::Direct(&Description::new("test".to_string()).unwrap()) + ); + assert_eq!( + invoice.expiry_time(), + Duration::from_secs(non_default_invoice_expiry_secs.into()) + ); // Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is // available. let chan = &nodes[1].node.list_usable_channels()[0]; assert_eq!(invoice.route_hints().len(), 1); assert_eq!(invoice.route_hints()[0].0.len(), 1); - assert_eq!(invoice.route_hints()[0].0[0].short_channel_id, chan.inbound_scid_alias.unwrap()); + assert_eq!( + invoice.route_hints()[0].0[0].short_channel_id, + chan.inbound_scid_alias.unwrap() + ); assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan.inbound_htlc_minimum_msat); assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat); let payment_event = { - nodes[0].node.pay_for_bolt11_invoice( - &invoice, PaymentId([42; 32]), None, RouteParametersConfig::default(), - Retry::Attempts(0) - ).unwrap(); + nodes[0] + .node + .pay_for_bolt11_invoice( + &invoice, + PaymentId([42; 32]), + None, + RouteParametersConfig::default(), + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); SendEvent::from_event(events.remove(0)) }; - nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test(nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + nodes[1] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + nodes[1].node.handle_commitment_signed_batch_test( + nodes[0].node.get_our_node_id(), + &payment_event.commitment_msg, + ); check_added_monitors(&nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); @@ -666,8 +762,14 @@ mod test { ..Default::default() }; let invoice = nodes[1].node.create_bolt11_invoice(invoice_params).unwrap(); - assert_eq!(invoice.min_final_cltv_expiry_delta(), if with_custom_delta { - custom_min_final_cltv_expiry_delta.unwrap() + 3 /* Buffer */} else { MIN_FINAL_CLTV_EXPIRY_DELTA } as u64); + assert_eq!( + invoice.min_final_cltv_expiry_delta(), + if with_custom_delta { + custom_min_final_cltv_expiry_delta.unwrap() + 3 /* Buffer */ + } else { + MIN_FINAL_CLTV_EXPIRY_DELTA + } as u64 + ); } #[test] @@ -703,9 +805,9 @@ mod test { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let description = Bolt11InvoiceDescription::Hash( - Sha256(Hash::hash("Testing description_hash".as_bytes())) - ); + let description = Bolt11InvoiceDescription::Hash(Sha256(Hash::hash( + "Testing description_hash".as_bytes(), + ))); let invoice_params = Bolt11InvoiceParameters { amount_msats: Some(10_000), description, @@ -715,7 +817,12 @@ mod test { let invoice = nodes[1].node.create_bolt11_invoice(invoice_params).unwrap(); assert_eq!(invoice.amount_milli_satoshis(), Some(10_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescriptionRef::Hash(&Sha256(Sha256::hash("Testing description_hash".as_bytes())))); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescriptionRef::Hash(&Sha256(Sha256::hash( + "Testing description_hash".as_bytes() + ))) + ); } #[test] @@ -726,9 +833,8 @@ mod test { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let payment_hash = PaymentHash([0; 32]); - let description = Bolt11InvoiceDescription::Direct( - Description::new("test".to_string()).unwrap() - ); + let description = + Bolt11InvoiceDescription::Direct(Description::new("test".to_string()).unwrap()); let invoice_params = Bolt11InvoiceParameters { amount_msats: Some(10_000), description, @@ -739,7 +845,10 @@ mod test { let invoice = nodes[1].node.create_bolt11_invoice(invoice_params).unwrap(); assert_eq!(invoice.amount_milli_satoshis(), Some(10_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescriptionRef::Direct(&Description::new("test".to_string()).unwrap())); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescriptionRef::Direct(&Description::new("test".to_string()).unwrap()) + ); assert_eq!(invoice.payment_hash(), &sha256::Hash::from_slice(&payment_hash.0[..]).unwrap()); } @@ -779,12 +888,14 @@ mod test { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let mut config = test_default_channel_config(); config.channel_handshake_config.minimum_depth = 1; - let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]); + let node_chanmgrs = + create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); // Create a private channel with lots of capacity and a lower value public channel (without // confirming the funding tx yet). - let unannounced_scid = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0); + let unannounced_scid = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0); let conf_tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 10_000, 0); // Before the channel is available, we should include the unannounced_scid. @@ -796,20 +907,37 @@ mod test { // channel we'll immediately switch to including it as a route hint, even though it isn't // yet announced. let pub_channel_scid = mine_transaction(&nodes[0], &conf_tx); - let node_a_pub_channel_ready = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id()); - nodes[1].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &node_a_pub_channel_ready); + let node_a_pub_channel_ready = get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ); + nodes[1] + .node + .handle_channel_ready(nodes[0].node.get_our_node_id(), &node_a_pub_channel_ready); assert_eq!(mine_transaction(&nodes[1], &conf_tx), pub_channel_scid); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); if let MessageSendEvent::SendChannelReady { msg, .. } = &events[0] { nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), msg); - } else { panic!(); } + } else { + panic!(); + } if let MessageSendEvent::SendChannelUpdate { msg, .. } = &events[1] { nodes[0].node.handle_channel_update(nodes[1].node.get_our_node_id(), msg); - } else { panic!(); } + } else { + panic!(); + } - nodes[1].node.handle_channel_update(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id())); + nodes[1].node.handle_channel_update( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ), + ); expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id()); @@ -826,7 +954,11 @@ mod test { connect_blocks(&nodes[1], 5); match_invoice_routes(Some(5000), &nodes[1], scid_aliases.clone()); connect_blocks(&nodes[1], 1); - get_event_msg!(nodes[1], MessageSendEvent::SendAnnouncementSignatures, nodes[0].node.get_our_node_id()); + get_event_msg!( + nodes[1], + MessageSendEvent::SendAnnouncementSignatures, + nodes[0].node.get_our_node_id() + ); match_invoice_routes(Some(5000), &nodes[1], HashSet::new()); } @@ -837,8 +969,10 @@ mod test { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); - let chan_2_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001); + let chan_1_0 = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); + let chan_2_0 = + create_unannounced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001); let mut scid_aliases = HashSet::new(); scid_aliases.insert(chan_1_0.0.short_channel_id_alias.unwrap()); @@ -854,9 +988,12 @@ mod test { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); - let _chan_1_0_inbound_below_amt = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 10_000, 0); - let _chan_1_0_large_inbound_above_amt = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 500_000, 0); - let chan_1_0_low_inbound_above_amt = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 200_000, 0); + let _chan_1_0_inbound_below_amt = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 10_000, 0); + let _chan_1_0_large_inbound_above_amt = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 500_000, 0); + let chan_1_0_low_inbound_above_amt = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 200_000, 0); let mut scid_aliases = HashSet::new(); scid_aliases.insert(chan_1_0_low_inbound_above_amt.0.short_channel_id_alias.unwrap()); @@ -940,31 +1077,70 @@ mod test { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); + let chan_1_0 = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); // Create an unannonced channel between `nodes[2]` and `nodes[0]`, for which the // `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate` // is never handled, the `channel.counterparty.forwarding_info` is never assigned. let mut private_chan_cfg = UserConfig::default(); private_chan_cfg.channel_handshake_config.announce_for_forwarding = false; - let temporary_channel_id = nodes[2].node.create_channel(nodes[0].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, Some(private_chan_cfg)).unwrap(); - let open_channel = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id()); + let temporary_channel_id = nodes[2] + .node + .create_channel( + nodes[0].node.get_our_node_id(), + 1_000_000, + 500_000_000, + 42, + None, + Some(private_chan_cfg), + ) + .unwrap(); + let open_channel = get_event_msg!( + nodes[2], + MessageSendEvent::SendOpenChannel, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_open_channel(nodes[2].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[0], MessageSendEvent::SendAcceptChannel, nodes[2].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[0], + MessageSendEvent::SendAcceptChannel, + nodes[2].node.get_our_node_id() + ); nodes[2].node.handle_accept_channel(nodes[0].node.get_our_node_id(), &accept_channel); let tx = sign_funding_transaction(&nodes[2], &nodes[0], 1_000_000, temporary_channel_id); - let conf_height = core::cmp::max(nodes[2].best_block_info().1 + 1, nodes[0].best_block_info().1 + 1); + let conf_height = + core::cmp::max(nodes[2].best_block_info().1 + 1, nodes[0].best_block_info().1 + 1); confirm_transaction_at(&nodes[2], &tx, conf_height); connect_blocks(&nodes[2], CHAN_CONFIRM_DEPTH - 1); confirm_transaction_at(&nodes[0], &tx, conf_height); connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH - 1); - let as_channel_ready = get_event_msg!(nodes[2], MessageSendEvent::SendChannelReady, nodes[0].node.get_our_node_id()); - nodes[2].node.handle_channel_ready(nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, nodes[2].node.get_our_node_id())); - get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id()); + let as_channel_ready = get_event_msg!( + nodes[2], + MessageSendEvent::SendChannelReady, + nodes[0].node.get_our_node_id() + ); + nodes[2].node.handle_channel_ready( + nodes[0].node.get_our_node_id(), + &get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelReady, + nodes[2].node.get_our_node_id() + ), + ); + get_event_msg!( + nodes[2], + MessageSendEvent::SendChannelUpdate, + nodes[0].node.get_our_node_id() + ); nodes[0].node.handle_channel_ready(nodes[2].node.get_our_node_id(), &as_channel_ready); - get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id()); + get_event_msg!( + nodes[0], + MessageSendEvent::SendChannelUpdate, + nodes[2].node.get_our_node_id() + ); expect_channel_ready_event(&nodes[0], &nodes[2].node.get_our_node_id()); expect_channel_ready_event(&nodes[2], &nodes[0].node.get_our_node_id()); @@ -982,7 +1158,8 @@ mod test { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let _chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); + let _chan_1_0 = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001); nodes[2].node.handle_channel_update(nodes[0].node.get_our_node_id(), &chan_2_0.1); @@ -1050,13 +1227,11 @@ mod test { } fn match_invoice_routes<'a, 'b: 'a, 'c: 'b>( - invoice_amt: Option, - invoice_node: &Node<'a, 'b, 'c>, - mut chan_ids_to_match: HashSet + invoice_amt: Option, invoice_node: &Node<'a, 'b, 'c>, + mut chan_ids_to_match: HashSet, ) { - let description = Bolt11InvoiceDescription::Direct( - Description::new("test".to_string()).unwrap() - ); + let description = + Bolt11InvoiceDescription::Direct(Description::new("test".to_string()).unwrap()); let invoice_params = Bolt11InvoiceParameters { amount_msats: invoice_amt, description, @@ -1070,7 +1245,11 @@ mod test { let hint_short_chan_id = hint.0[0].short_channel_id; assert!(chan_ids_to_match.remove(&hint_short_chan_id)); } - assert!(chan_ids_to_match.is_empty(), "Unmatched short channel ids: {:?}", chan_ids_to_match); + assert!( + chan_ids_to_match.is_empty(), + "Unmatched short channel ids: {:?}", + chan_ids_to_match + ); } #[test] @@ -1106,10 +1285,8 @@ mod test { nodes[2].node.handle_channel_update(nodes[0].node.get_our_node_id(), &chan_0_2.0); let payment_amt = 10_000; - let route_hints = vec![ - nodes[1].node.get_phantom_route_hints(), - nodes[2].node.get_phantom_route_hints(), - ]; + let route_hints = + vec![nodes[1].node.get_phantom_route_hints(), nodes[2].node.get_phantom_route_hints()]; let user_payment_preimage = PaymentPreimage([1; 32]); let payment_hash = if user_generated_pmt_hash { @@ -1117,16 +1294,30 @@ mod test { } else { None }; - let genesis_timestamp = bitcoin::constants::genesis_block(bitcoin::Network::Testnet).header.time as u64; + let genesis_timestamp = + bitcoin::constants::genesis_block(bitcoin::Network::Testnet).header.time as u64; let non_default_invoice_expiry_secs = 4200; - let invoice = - create_phantom_invoice::<&test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger>( - Some(payment_amt), payment_hash, "test".to_string(), non_default_invoice_expiry_secs, - route_hints, nodes[1].keys_manager, nodes[1].keys_manager, nodes[1].logger, - Currency::BitcoinTestnet, None, Duration::from_secs(genesis_timestamp) - ).unwrap(); - let (payment_hash, payment_secret) = (PaymentHash(invoice.payment_hash().to_byte_array()), *invoice.payment_secret()); + let invoice = create_phantom_invoice::< + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestLogger, + >( + Some(payment_amt), + payment_hash, + "test".to_string(), + non_default_invoice_expiry_secs, + route_hints, + nodes[1].keys_manager, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + None, + Duration::from_secs(genesis_timestamp), + ) + .unwrap(); + let (payment_hash, payment_secret) = + (PaymentHash(invoice.payment_hash().to_byte_array()), *invoice.payment_secret()); let payment_preimage = if user_generated_pmt_hash { user_payment_preimage } else { @@ -1134,22 +1325,41 @@ mod test { }; assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.description(), Bolt11InvoiceDescriptionRef::Direct(&Description::new("test".to_string()).unwrap())); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescriptionRef::Direct(&Description::new("test".to_string()).unwrap()) + ); assert_eq!(invoice.route_hints().len(), 2); - assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into())); + assert_eq!( + invoice.expiry_time(), + Duration::from_secs(non_default_invoice_expiry_secs.into()) + ); assert!(!invoice.features().unwrap().supports_basic_mpp()); - let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key(), - invoice.min_final_cltv_expiry_delta() as u32) - .with_bolt11_features(invoice.features().unwrap().clone()).unwrap() - .with_route_hints(invoice.route_hints()).unwrap(); + let payment_params = PaymentParameters::from_node_id( + invoice.recover_payee_pub_key(), + invoice.min_final_cltv_expiry_delta() as u32, + ) + .with_bolt11_features(invoice.features().unwrap().clone()) + .unwrap() + .with_route_hints(invoice.route_hints()) + .unwrap(); let params = RouteParameters::from_payment_params_and_value( - payment_params, invoice.amount_milli_satoshis().unwrap()); + payment_params, + invoice.amount_milli_satoshis().unwrap(), + ); let (payment_event, fwd_idx) = { let payment_hash = PaymentHash(invoice.payment_hash().to_byte_array()); - nodes[0].node.send_payment(payment_hash, - RecipientOnionFields::secret_only(*invoice.payment_secret()), - PaymentId(payment_hash.0), params, Retry::Attempts(0)).unwrap(); + nodes[0] + .node + .send_payment( + payment_hash, + RecipientOnionFields::secret_only(*invoice.payment_secret()), + PaymentId(payment_hash.0), + params, + Retry::Attempts(0), + ) + .unwrap(); check_added_monitors(&nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -1158,14 +1368,24 @@ mod test { MessageSendEvent::UpdateHTLCs { node_id, .. } => { if node_id == nodes[1].node.get_our_node_id() { 1 - } else { 2 } + } else { + 2 + } }, - _ => panic!("Unexpected event") + _ => panic!("Unexpected event"), }; (SendEvent::from_event(events.remove(0)), fwd_idx) }; - nodes[fwd_idx].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); - commitment_signed_dance!(nodes[fwd_idx], nodes[0], &payment_event.commitment_msg, false, true); + nodes[fwd_idx] + .node + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); + commitment_signed_dance!( + nodes[fwd_idx], + nodes[0], + &payment_event.commitment_msg, + false, + true + ); // Note that we have to "forward pending HTLCs" twice before we see the PaymentClaimable as // this "emulates" the payment taking two hops, providing some privacy to make phantom node @@ -1182,12 +1402,22 @@ mod test { nodes[fwd_idx].node.process_pending_events(&forward_event_handler); nodes[fwd_idx].node.process_pending_events(&forward_event_handler); - let payment_preimage_opt = if user_generated_pmt_hash { None } else { Some(payment_preimage) }; + let payment_preimage_opt = + if user_generated_pmt_hash { None } else { Some(payment_preimage) }; assert_eq!(other_events.borrow().len(), 1); - check_payment_claimable(&other_events.borrow()[0], payment_hash, payment_secret, payment_amt, payment_preimage_opt, invoice.recover_payee_pub_key()); - do_claim_payment_along_route( - ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[fwd_idx]]], payment_preimage) + check_payment_claimable( + &other_events.borrow()[0], + payment_hash, + payment_secret, + payment_amt, + payment_preimage_opt, + invoice.recover_payee_pub_key(), ); + do_claim_payment_along_route(ClaimAlongRouteArgs::new( + &nodes[0], + &[&[&nodes[fwd_idx]]], + payment_preimage, + )); expect_payment_sent(&nodes[0], payment_preimage, None, true, true); } @@ -1206,24 +1436,49 @@ mod test { create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); let payment_amt = 20_000; - let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600, None).unwrap(); - let route_hints = vec![ - nodes[1].node.get_phantom_route_hints(), - nodes[2].node.get_phantom_route_hints(), - ]; - - let invoice = create_phantom_invoice::<&test_utils::TestKeysInterface, - &test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), Some(payment_hash), - "test".to_string(), 3600, route_hints, nodes[1].keys_manager, nodes[1].keys_manager, - nodes[1].logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap(); + let (payment_hash, _payment_secret) = + nodes[1].node.create_inbound_payment(Some(payment_amt), 3600, None).unwrap(); + let route_hints = + vec![nodes[1].node.get_phantom_route_hints(), nodes[2].node.get_phantom_route_hints()]; + + let invoice = create_phantom_invoice::< + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestLogger, + >( + Some(payment_amt), + Some(payment_hash), + "test".to_string(), + 3600, + route_hints, + nodes[1].keys_manager, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + None, + Duration::from_secs(1234567), + ) + .unwrap(); let chan_0_1 = &nodes[1].node.list_usable_channels()[0]; - assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan_0_1.inbound_htlc_minimum_msat); - assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan_0_1.inbound_htlc_maximum_msat); + assert_eq!( + invoice.route_hints()[0].0[0].htlc_minimum_msat, + chan_0_1.inbound_htlc_minimum_msat + ); + assert_eq!( + invoice.route_hints()[0].0[0].htlc_maximum_msat, + chan_0_1.inbound_htlc_maximum_msat + ); let chan_0_2 = &nodes[2].node.list_usable_channels()[0]; - assert_eq!(invoice.route_hints()[1].0[0].htlc_minimum_msat, chan_0_2.inbound_htlc_minimum_msat); - assert_eq!(invoice.route_hints()[1].0[0].htlc_maximum_msat, chan_0_2.inbound_htlc_maximum_msat); + assert_eq!( + invoice.route_hints()[1].0[0].htlc_minimum_msat, + chan_0_2.inbound_htlc_minimum_msat + ); + assert_eq!( + invoice.route_hints()[1].0[0].htlc_maximum_msat, + chan_0_2.inbound_htlc_maximum_msat + ); } #[test] @@ -1234,25 +1489,41 @@ mod test { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let payment_amt = 20_000; - let route_hints = vec![ - nodes[1].node.get_phantom_route_hints(), - nodes[2].node.get_phantom_route_hints(), - ]; + let route_hints = + vec![nodes[1].node.get_phantom_route_hints(), nodes[2].node.get_phantom_route_hints()]; let description_hash = Sha256(Hash::hash("Description hash phantom invoice".as_bytes())); let non_default_invoice_expiry_secs = 4200; let invoice = create_phantom_invoice_with_description_hash::< - &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestLogger, + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestLogger, >( - Some(payment_amt), None, non_default_invoice_expiry_secs, description_hash, - route_hints, nodes[1].keys_manager, nodes[1].keys_manager, nodes[1].logger, - Currency::BitcoinTestnet, None, Duration::from_secs(1234567), + Some(payment_amt), + None, + non_default_invoice_expiry_secs, + description_hash, + route_hints, + nodes[1].keys_manager, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + None, + Duration::from_secs(1234567), ) .unwrap(); assert_eq!(invoice.amount_milli_satoshis(), Some(20_000)); assert_eq!(invoice.min_final_cltv_expiry_delta(), MIN_FINAL_CLTV_EXPIRY_DELTA as u64); - assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into())); - assert_eq!(invoice.description(), Bolt11InvoiceDescriptionRef::Hash(&Sha256(Sha256::hash("Description hash phantom invoice".as_bytes())))); + assert_eq!( + invoice.expiry_time(), + Duration::from_secs(non_default_invoice_expiry_secs.into()) + ); + assert_eq!( + invoice.description(), + Bolt11InvoiceDescriptionRef::Hash(&Sha256(Sha256::hash( + "Description hash phantom invoice".as_bytes() + ))) + ); } #[test] @@ -1263,22 +1534,41 @@ mod test { let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let payment_amt = 20_000; - let route_hints = vec![ - nodes[1].node.get_phantom_route_hints(), - nodes[2].node.get_phantom_route_hints(), - ]; + let route_hints = + vec![nodes[1].node.get_phantom_route_hints(), nodes[2].node.get_phantom_route_hints()]; let user_payment_preimage = PaymentPreimage([1; 32]); - let payment_hash = Some(PaymentHash(Sha256::hash(&user_payment_preimage.0[..]).to_byte_array())); + let payment_hash = + Some(PaymentHash(Sha256::hash(&user_payment_preimage.0[..]).to_byte_array())); let non_default_invoice_expiry_secs = 4200; let min_final_cltv_expiry_delta = Some(100); let duration_since_epoch = Duration::from_secs(1234567); - let invoice = create_phantom_invoice::<&test_utils::TestKeysInterface, - &test_utils::TestKeysInterface, &test_utils::TestLogger>(Some(payment_amt), payment_hash, - "".to_string(), non_default_invoice_expiry_secs, route_hints, nodes[1].keys_manager, nodes[1].keys_manager, - nodes[1].logger, Currency::BitcoinTestnet, min_final_cltv_expiry_delta, duration_since_epoch).unwrap(); + let invoice = create_phantom_invoice::< + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestLogger, + >( + Some(payment_amt), + payment_hash, + "".to_string(), + non_default_invoice_expiry_secs, + route_hints, + nodes[1].keys_manager, + nodes[1].keys_manager, + nodes[1].logger, + Currency::BitcoinTestnet, + min_final_cltv_expiry_delta, + duration_since_epoch, + ) + .unwrap(); assert_eq!(invoice.amount_milli_satoshis(), Some(20_000)); - assert_eq!(invoice.min_final_cltv_expiry_delta(), (min_final_cltv_expiry_delta.unwrap() + 3) as u64); - assert_eq!(invoice.expiry_time(), Duration::from_secs(non_default_invoice_expiry_secs.into())); + assert_eq!( + invoice.min_final_cltv_expiry_delta(), + (min_final_cltv_expiry_delta.unwrap() + 3) as u64 + ); + assert_eq!( + invoice.expiry_time(), + Duration::from_secs(non_default_invoice_expiry_secs.into()) + ); } #[test] @@ -1292,8 +1582,10 @@ mod test { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let chan_0_1 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); - let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); + let chan_0_1 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); + let chan_0_2 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); let mut scid_aliases = HashSet::new(); scid_aliases.insert(chan_0_1.0.short_channel_id_alias.unwrap()); @@ -1302,14 +1594,15 @@ mod test { match_multi_node_invoice_routes( Some(10_000), &nodes[1], - vec![&nodes[1], &nodes[2],], + vec![&nodes[1], &nodes[2]], scid_aliases, - false + false, ); } #[test] - fn test_multi_node_hints_includes_one_channel_of_each_counterparty_nodes_per_participating_node() { + fn test_multi_node_hints_includes_one_channel_of_each_counterparty_nodes_per_participating_node( + ) { let mut chanmon_cfgs = create_chanmon_cfgs(4); let seed_1 = [42u8; 32]; let seed_2 = [43u8; 32]; @@ -1319,9 +1612,12 @@ mod test { let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); - let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); - let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001); - let chan_1_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 3_000_000, 10005); + let chan_0_2 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); + let chan_0_3 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001); + let chan_1_3 = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 3_000_000, 10005); let mut scid_aliases = HashSet::new(); scid_aliases.insert(chan_0_2.0.short_channel_id_alias.unwrap()); @@ -1331,9 +1627,9 @@ mod test { match_multi_node_invoice_routes( Some(10_000), &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases, - false + false, ); } @@ -1348,32 +1644,72 @@ mod test { let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); - let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); - let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001); + let chan_0_2 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); + let chan_0_3 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 1000000, 10001); // Create an unannonced channel between `nodes[1]` and `nodes[3]`, for which the // `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate` // is never handled, the `channel.counterparty.forwarding_info` is never assigned. let mut private_chan_cfg = UserConfig::default(); private_chan_cfg.channel_handshake_config.announce_for_forwarding = false; - let temporary_channel_id = nodes[1].node.create_channel(nodes[3].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None, Some(private_chan_cfg)).unwrap(); - let open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[3].node.get_our_node_id()); + let temporary_channel_id = nodes[1] + .node + .create_channel( + nodes[3].node.get_our_node_id(), + 1_000_000, + 500_000_000, + 42, + None, + Some(private_chan_cfg), + ) + .unwrap(); + let open_channel = get_event_msg!( + nodes[1], + MessageSendEvent::SendOpenChannel, + nodes[3].node.get_our_node_id() + ); nodes[3].node.handle_open_channel(nodes[1].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!(nodes[3], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id()); + let accept_channel = get_event_msg!( + nodes[3], + MessageSendEvent::SendAcceptChannel, + nodes[1].node.get_our_node_id() + ); nodes[1].node.handle_accept_channel(nodes[3].node.get_our_node_id(), &accept_channel); let tx = sign_funding_transaction(&nodes[1], &nodes[3], 1_000_000, temporary_channel_id); - let conf_height = core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[3].best_block_info().1 + 1); + let conf_height = + core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[3].best_block_info().1 + 1); confirm_transaction_at(&nodes[1], &tx, conf_height); connect_blocks(&nodes[1], CHAN_CONFIRM_DEPTH - 1); confirm_transaction_at(&nodes[3], &tx, conf_height); connect_blocks(&nodes[3], CHAN_CONFIRM_DEPTH - 1); - let as_channel_ready = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, nodes[3].node.get_our_node_id()); - nodes[1].node.handle_channel_ready(nodes[3].node.get_our_node_id(), &get_event_msg!(nodes[3], MessageSendEvent::SendChannelReady, nodes[1].node.get_our_node_id())); - get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[3].node.get_our_node_id()); + let as_channel_ready = get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelReady, + nodes[3].node.get_our_node_id() + ); + nodes[1].node.handle_channel_ready( + nodes[3].node.get_our_node_id(), + &get_event_msg!( + nodes[3], + MessageSendEvent::SendChannelReady, + nodes[1].node.get_our_node_id() + ), + ); + get_event_msg!( + nodes[1], + MessageSendEvent::SendChannelUpdate, + nodes[3].node.get_our_node_id() + ); nodes[3].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &as_channel_ready); - get_event_msg!(nodes[3], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id()); + get_event_msg!( + nodes[3], + MessageSendEvent::SendChannelUpdate, + nodes[1].node.get_our_node_id() + ); expect_channel_ready_event(&nodes[1], &nodes[3].node.get_our_node_id()); expect_channel_ready_event(&nodes[3], &nodes[1].node.get_our_node_id()); @@ -1387,9 +1723,9 @@ mod test { match_multi_node_invoice_routes( Some(10_000), &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases, - false + false, ); } @@ -1404,7 +1740,8 @@ mod test { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let chan_0_1 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); + let chan_0_1 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); let chan_2_0 = create_announced_chan_between_nodes_with_value(&nodes, 2, 0, 100000, 10001); nodes[2].node.handle_channel_update(nodes[0].node.get_our_node_id(), &chan_2_0.1); @@ -1418,9 +1755,9 @@ mod test { match_multi_node_invoice_routes( Some(10_000), &nodes[1], - vec![&nodes[1], &nodes[2],], + vec![&nodes[1], &nodes[2]], scid_aliases, - true + true, ); } @@ -1438,9 +1775,11 @@ mod test { let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); nodes[0].node.handle_channel_update(nodes[2].node.get_our_node_id(), &chan_0_2.1); nodes[2].node.handle_channel_update(nodes[0].node.get_our_node_id(), &chan_0_2.0); - let _chan_1_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001); + let _chan_1_2 = + create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001); - let chan_0_3 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 100000, 10001); + let chan_0_3 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 3, 100000, 10001); // Hints should include `chan_0_3` from as `nodes[3]` only have private channels, and no // channels for `nodes[2]` as it contains a mix of public and private channels. @@ -1450,9 +1789,9 @@ mod test { match_multi_node_invoice_routes( Some(10_000), &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases, - true + true, ); } @@ -1467,10 +1806,14 @@ mod test { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); - let _chan_0_1_below_amt = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); - let _chan_0_1_above_amt_high_inbound = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 500_000, 0); - let chan_0_1_above_amt_low_inbound = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 180_000, 0); - let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); + let _chan_0_1_below_amt = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0); + let _chan_0_1_above_amt_high_inbound = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 500_000, 0); + let chan_0_1_above_amt_low_inbound = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 180_000, 0); + let chan_0_2 = + create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); let mut scid_aliases = HashSet::new(); scid_aliases.insert(chan_0_1_above_amt_low_inbound.0.short_channel_id_alias.unwrap()); @@ -1479,9 +1822,9 @@ mod test { match_multi_node_invoice_routes( Some(100_000_000), &nodes[1], - vec![&nodes[1], &nodes[2],], + vec![&nodes[1], &nodes[2]], scid_aliases, - false + false, ); } @@ -1508,9 +1851,9 @@ mod test { match_multi_node_invoice_routes( Some(99_000_001), &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases_99_000_001_msat, - false + false, ); // Since the invoice is exactly at chan_0_3's inbound capacity, it should be included. @@ -1522,9 +1865,9 @@ mod test { match_multi_node_invoice_routes( Some(99_000_000), &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases_99_000_000_msat, - false + false, ); // Since the invoice is above all of `nodes[2]` channels' inbound capacity, all of @@ -1537,9 +1880,9 @@ mod test { match_multi_node_invoice_routes( Some(300_000_000), &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases_300_000_000_msat, - false + false, ); // Since the no specified amount, all channels should included. @@ -1551,9 +1894,9 @@ mod test { match_multi_node_invoice_routes( None, &nodes[2], - vec![&nodes[2], &nodes[3],], + vec![&nodes[2], &nodes[3]], scid_aliases_no_specified_amount, - false + false, ); } @@ -1569,7 +1912,8 @@ mod test { chanmon_cfgs[4].keys_manager.backing = make_dyn_keys_interface(&seed_3); chanmon_cfgs[4].keys_manager.backing = make_dyn_keys_interface(&seed_4); let node_cfgs = create_node_cfgs(6, &chanmon_cfgs); - let node_chanmgrs = create_node_chanmgrs(6, &node_cfgs, &[None, None, None, None, None, None]); + let node_chanmgrs = + create_node_chanmgrs(6, &node_cfgs, &[None, None, None, None, None, None]); let nodes = create_network(6, &node_cfgs, &node_chanmgrs); // Setup each phantom node with two channels from distinct peers. @@ -1641,30 +1985,44 @@ mod test { match_multi_node_invoice_routes( Some(100_000_000), &nodes[3], - vec![&nodes[3], &nodes[4],], + vec![&nodes[3], &nodes[4]], scid_aliases, false, ); } fn match_multi_node_invoice_routes<'a, 'b: 'a, 'c: 'b>( - invoice_amt: Option, - invoice_node: &Node<'a, 'b, 'c>, - network_multi_nodes: Vec<&Node<'a, 'b, 'c>>, - mut chan_ids_to_match: HashSet, - nodes_contains_public_channels: bool - ){ - let phantom_route_hints = network_multi_nodes.iter() + invoice_amt: Option, invoice_node: &Node<'a, 'b, 'c>, + network_multi_nodes: Vec<&Node<'a, 'b, 'c>>, mut chan_ids_to_match: HashSet, + nodes_contains_public_channels: bool, + ) { + let phantom_route_hints = network_multi_nodes + .iter() .map(|node| node.node.get_phantom_route_hints()) .collect::>(); - let phantom_scids = phantom_route_hints.iter() + let phantom_scids = phantom_route_hints + .iter() .map(|route_hint| route_hint.phantom_scid) .collect::>(); - let invoice = create_phantom_invoice::<&test_utils::TestKeysInterface, - &test_utils::TestKeysInterface, &test_utils::TestLogger>(invoice_amt, None, "test".to_string(), - 3600, phantom_route_hints, invoice_node.keys_manager, invoice_node.keys_manager, - invoice_node.logger, Currency::BitcoinTestnet, None, Duration::from_secs(1234567)).unwrap(); + let invoice = create_phantom_invoice::< + &test_utils::TestKeysInterface, + &test_utils::TestKeysInterface, + &test_utils::TestLogger, + >( + invoice_amt, + None, + "test".to_string(), + 3600, + phantom_route_hints, + invoice_node.keys_manager, + invoice_node.keys_manager, + invoice_node.logger, + Currency::BitcoinTestnet, + None, + Duration::from_secs(1234567), + ) + .unwrap(); let invoice_hints = invoice.private_routes(); @@ -1682,10 +2040,14 @@ mod test { let phantom_scid = hints[1].short_channel_id; assert!(phantom_scids.contains(&phantom_scid)); }, - _ => panic!("Incorrect hint length generated") + _ => panic!("Incorrect hint length generated"), } } - assert!(chan_ids_to_match.is_empty(), "Unmatched short channel ids: {:?}", chan_ids_to_match); + assert!( + chan_ids_to_match.is_empty(), + "Unmatched short channel ids: {:?}", + chan_ids_to_match + ); } #[test] @@ -1696,7 +2058,7 @@ mod test { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let description = Bolt11InvoiceDescription::Direct( - Description::new("Some description".to_string()).unwrap() + Description::new("Some description".to_string()).unwrap(), ); let invoice_params = Bolt11InvoiceParameters { amount_msats: Some(10_000), @@ -1706,7 +2068,9 @@ mod test { ..Default::default() }; match nodes[1].node.create_bolt11_invoice(invoice_params) { - Err(SignOrCreationError::CreationError(CreationError::MinFinalCltvExpiryDeltaTooShort)) => {}, + Err(SignOrCreationError::CreationError( + CreationError::MinFinalCltvExpiryDeltaTooShort, + )) => {}, _ => panic!(), } } @@ -1735,7 +2099,11 @@ mod test { assert_eq!(expected, result); // test three nestend vectors - let a = vec![vec!["a0"].into_iter(), vec!["a1", "b1", "c1"].into_iter(), vec!["a2"].into_iter()]; + let a = vec![ + vec!["a0"].into_iter(), + vec!["a1", "b1", "c1"].into_iter(), + vec!["a2"].into_iter(), + ]; let result = rotate_through_iterators(a).collect::>(); let expected = vec!["a0", "a1", "a2", "b1", "c1"]; @@ -1749,24 +2117,25 @@ mod test { assert_eq!(expected, result); // test single empty nested vector - let a:Vec> = vec![vec![].into_iter()]; + let a: Vec> = vec![vec![].into_iter()]; let result = rotate_through_iterators(a).collect::>(); - let expected:Vec<&str> = vec![]; + let expected: Vec<&str> = vec![]; assert_eq!(expected, result); // test first nested vector is empty - let a:Vec>= vec![vec![].into_iter(), vec!["a1", "b1", "c1"].into_iter()]; + let a: Vec> = + vec![vec![].into_iter(), vec!["a1", "b1", "c1"].into_iter()]; let result = rotate_through_iterators(a).collect::>(); let expected = vec!["a1", "b1", "c1"]; assert_eq!(expected, result); // test two empty vectors - let a:Vec> = vec![vec![].into_iter(), vec![].into_iter()]; + let a: Vec> = vec![vec![].into_iter(), vec![].into_iter()]; let result = rotate_through_iterators(a).collect::>(); - let expected:Vec<&str> = vec![]; + let expected: Vec<&str> = vec![]; assert_eq!(expected, result); // test an empty vector amongst other filled vectors diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index af1bb4a57fa..7f920c51b77 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -17,7 +17,6 @@ lightning/src/ln/channelmanager.rs lightning/src/ln/functional_test_utils.rs lightning/src/ln/functional_tests.rs lightning/src/ln/inbound_payment.rs -lightning/src/ln/invoice_utils.rs lightning/src/ln/max_payment_path_len_tests.rs lightning/src/ln/mod.rs lightning/src/ln/monitor_tests.rs From aadff797e2e86b42501cbe767b0f9a8e5499aaaf Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 21:10:15 +0000 Subject: [PATCH 10/11] Clean up `invoice_utils` functional tests somewhat --- lightning/src/ln/invoice_utils.rs | 229 +++++++++--------------------- 1 file changed, 71 insertions(+), 158 deletions(-) diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs index a33f5b788ec..f2e8284a617 100644 --- a/lightning/src/ln/invoice_utils.rs +++ b/lightning/src/ln/invoice_utils.rs @@ -630,7 +630,7 @@ mod test { }; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, MessageSendEvent}; - use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig}; + use crate::routing::router::{PaymentParameters, RouteParameters}; use crate::sign::PhantomKeysManager; use crate::types::payment::{PaymentHash, PaymentPreimage}; use crate::util::config::UserConfig; @@ -680,6 +680,8 @@ mod test { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001); + let node_a_id = nodes[0].node.get_our_node_id(); + let description = Bolt11InvoiceDescription::Direct(Description::new("test".to_string()).unwrap()); let non_default_invoice_expiry_secs = 4200; @@ -715,30 +717,18 @@ mod test { assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan.inbound_htlc_minimum_msat); assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat); - let payment_event = { - nodes[0] - .node - .pay_for_bolt11_invoice( - &invoice, - PaymentId([42; 32]), - None, - RouteParametersConfig::default(), - Retry::Attempts(0), - ) - .unwrap(); - check_added_monitors(&nodes[0], 1); - - let mut events = nodes[0].node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - SendEvent::from_event(events.remove(0)) - }; - nodes[1] + let retry = Retry::Attempts(0); + nodes[0] .node - .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); - nodes[1].node.handle_commitment_signed_batch_test( - nodes[0].node.get_our_node_id(), - &payment_event.commitment_msg, - ); + .pay_for_bolt11_invoice(&invoice, PaymentId([42; 32]), None, Default::default(), retry) + .unwrap(); + check_added_monitors(&nodes[0], 1); + + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let payment_event = SendEvent::from_event(events.remove(0)); + nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event.msgs[0]); + nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &payment_event.commitment_msg); check_added_monitors(&nodes[1], 1); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); @@ -892,6 +882,9 @@ mod test { create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + let node_a_id = nodes[0].node.get_our_node_id(); + let node_b_id = nodes[1].node.get_our_node_id(); + // Create a private channel with lots of capacity and a lower value public channel (without // confirming the funding tx yet). let unannounced_scid = @@ -907,40 +900,29 @@ mod test { // channel we'll immediately switch to including it as a route hint, even though it isn't // yet announced. let pub_channel_scid = mine_transaction(&nodes[0], &conf_tx); - let node_a_pub_channel_ready = get_event_msg!( - nodes[0], - MessageSendEvent::SendChannelReady, - nodes[1].node.get_our_node_id() - ); - nodes[1] - .node - .handle_channel_ready(nodes[0].node.get_our_node_id(), &node_a_pub_channel_ready); + let node_a_pub_channel_ready = + get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_b_id); + nodes[1].node.handle_channel_ready(node_a_id, &node_a_pub_channel_ready); assert_eq!(mine_transaction(&nodes[1], &conf_tx), pub_channel_scid); let events = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 2); if let MessageSendEvent::SendChannelReady { msg, .. } = &events[0] { - nodes[0].node.handle_channel_ready(nodes[1].node.get_our_node_id(), msg); + nodes[0].node.handle_channel_ready(node_b_id, msg); } else { panic!(); } if let MessageSendEvent::SendChannelUpdate { msg, .. } = &events[1] { - nodes[0].node.handle_channel_update(nodes[1].node.get_our_node_id(), msg); + nodes[0].node.handle_channel_update(node_b_id, msg); } else { panic!(); } - nodes[1].node.handle_channel_update( - nodes[0].node.get_our_node_id(), - &get_event_msg!( - nodes[0], - MessageSendEvent::SendChannelUpdate, - nodes[1].node.get_our_node_id() - ), - ); + let as_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, node_b_id); + nodes[1].node.handle_channel_update(node_a_id, &as_update); - expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id()); - expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id()); + expect_channel_ready_event(&nodes[0], &node_b_id); + expect_channel_ready_event(&nodes[1], &node_a_id); scid_aliases.clear(); scid_aliases.insert(node_a_pub_channel_ready.short_channel_id_alias.unwrap()); @@ -954,11 +936,7 @@ mod test { connect_blocks(&nodes[1], 5); match_invoice_routes(Some(5000), &nodes[1], scid_aliases.clone()); connect_blocks(&nodes[1], 1); - get_event_msg!( - nodes[1], - MessageSendEvent::SendAnnouncementSignatures, - nodes[0].node.get_our_node_id() - ); + get_event_msg!(nodes[1], MessageSendEvent::SendAnnouncementSignatures, node_a_id); match_invoice_routes(Some(5000), &nodes[1], HashSet::new()); } @@ -1080,6 +1058,9 @@ mod test { let chan_1_0 = create_unannounced_chan_between_nodes_with_value(&nodes, 1, 0, 100000, 10001); + let node_a_id = nodes[0].node.get_our_node_id(); + let node_c_id = nodes[2].node.get_our_node_id(); + // Create an unannonced channel between `nodes[2]` and `nodes[0]`, for which the // `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate` // is never handled, the `channel.counterparty.forwarding_info` is never assigned. @@ -1087,27 +1068,13 @@ mod test { private_chan_cfg.channel_handshake_config.announce_for_forwarding = false; let temporary_channel_id = nodes[2] .node - .create_channel( - nodes[0].node.get_our_node_id(), - 1_000_000, - 500_000_000, - 42, - None, - Some(private_chan_cfg), - ) + .create_channel(node_a_id, 1_000_000, 500_000_000, 42, None, Some(private_chan_cfg)) .unwrap(); - let open_channel = get_event_msg!( - nodes[2], - MessageSendEvent::SendOpenChannel, - nodes[0].node.get_our_node_id() - ); - nodes[0].node.handle_open_channel(nodes[2].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!( - nodes[0], - MessageSendEvent::SendAcceptChannel, - nodes[2].node.get_our_node_id() - ); - nodes[2].node.handle_accept_channel(nodes[0].node.get_our_node_id(), &accept_channel); + let open_channel = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, node_a_id); + nodes[0].node.handle_open_channel(node_c_id, &open_channel); + let accept_channel = + get_event_msg!(nodes[0], MessageSendEvent::SendAcceptChannel, node_c_id); + nodes[2].node.handle_accept_channel(node_a_id, &accept_channel); let tx = sign_funding_transaction(&nodes[2], &nodes[0], 1_000_000, temporary_channel_id); @@ -1117,32 +1084,16 @@ mod test { connect_blocks(&nodes[2], CHAN_CONFIRM_DEPTH - 1); confirm_transaction_at(&nodes[0], &tx, conf_height); connect_blocks(&nodes[0], CHAN_CONFIRM_DEPTH - 1); - let as_channel_ready = get_event_msg!( - nodes[2], - MessageSendEvent::SendChannelReady, - nodes[0].node.get_our_node_id() - ); - nodes[2].node.handle_channel_ready( - nodes[0].node.get_our_node_id(), - &get_event_msg!( - nodes[0], - MessageSendEvent::SendChannelReady, - nodes[2].node.get_our_node_id() - ), - ); - get_event_msg!( - nodes[2], - MessageSendEvent::SendChannelUpdate, - nodes[0].node.get_our_node_id() - ); - nodes[0].node.handle_channel_ready(nodes[2].node.get_our_node_id(), &as_channel_ready); - get_event_msg!( - nodes[0], - MessageSendEvent::SendChannelUpdate, - nodes[2].node.get_our_node_id() - ); - expect_channel_ready_event(&nodes[0], &nodes[2].node.get_our_node_id()); - expect_channel_ready_event(&nodes[2], &nodes[0].node.get_our_node_id()); + let as_channel_ready = + get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_c_id); + let cs_channel_ready = + get_event_msg!(nodes[2], MessageSendEvent::SendChannelReady, node_a_id); + nodes[2].node.handle_channel_ready(node_a_id, &as_channel_ready); + get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, node_a_id); + nodes[0].node.handle_channel_ready(node_c_id, &cs_channel_ready); + get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, node_c_id); + expect_channel_ready_event(&nodes[0], &node_c_id); + expect_channel_ready_event(&nodes[2], &node_a_id); // As `msgs::ChannelUpdate` was never handled for the participating node(s) of the second // channel, the channel will never be assigned any `counterparty.forwarding_info`. @@ -1348,20 +1299,14 @@ mod test { payment_params, invoice.amount_milli_satoshis().unwrap(), ); - let (payment_event, fwd_idx) = { - let payment_hash = PaymentHash(invoice.payment_hash().to_byte_array()); - nodes[0] - .node - .send_payment( - payment_hash, - RecipientOnionFields::secret_only(*invoice.payment_secret()), - PaymentId(payment_hash.0), - params, - Retry::Attempts(0), - ) - .unwrap(); - check_added_monitors(&nodes[0], 1); + let payment_hash = PaymentHash(invoice.payment_hash().to_byte_array()); + let id = PaymentId(payment_hash.0); + let onion = RecipientOnionFields::secret_only(*invoice.payment_secret()); + nodes[0].node.send_payment(payment_hash, onion, id, params, Retry::Attempts(0)).unwrap(); + check_added_monitors(&nodes[0], 1); + + let (send_event, fwd_idx) = { let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); let fwd_idx = match events[0] { @@ -1378,14 +1323,8 @@ mod test { }; nodes[fwd_idx] .node - .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); - commitment_signed_dance!( - nodes[fwd_idx], - nodes[0], - &payment_event.commitment_msg, - false, - true - ); + .handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_event.msgs[0]); + commitment_signed_dance!(nodes[fwd_idx], nodes[0], &send_event.commitment_msg, false, true); // Note that we have to "forward pending HTLCs" twice before we see the PaymentClaimable as // this "emulates" the payment taking two hops, providing some privacy to make phantom node @@ -1644,6 +1583,9 @@ mod test { let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let nodes = create_network(4, &node_cfgs, &node_chanmgrs); + let node_b_id = nodes[1].node.get_our_node_id(); + let node_d_id = nodes[3].node.get_our_node_id(); + let chan_0_2 = create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001); let chan_0_3 = @@ -1656,26 +1598,12 @@ mod test { private_chan_cfg.channel_handshake_config.announce_for_forwarding = false; let temporary_channel_id = nodes[1] .node - .create_channel( - nodes[3].node.get_our_node_id(), - 1_000_000, - 500_000_000, - 42, - None, - Some(private_chan_cfg), - ) + .create_channel(node_d_id, 1_000_000, 500_000_000, 42, None, Some(private_chan_cfg)) .unwrap(); - let open_channel = get_event_msg!( - nodes[1], - MessageSendEvent::SendOpenChannel, - nodes[3].node.get_our_node_id() - ); + let open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, node_d_id); nodes[3].node.handle_open_channel(nodes[1].node.get_our_node_id(), &open_channel); - let accept_channel = get_event_msg!( - nodes[3], - MessageSendEvent::SendAcceptChannel, - nodes[1].node.get_our_node_id() - ); + let accept_channel = + get_event_msg!(nodes[3], MessageSendEvent::SendAcceptChannel, node_b_id); nodes[1].node.handle_accept_channel(nodes[3].node.get_our_node_id(), &accept_channel); let tx = sign_funding_transaction(&nodes[1], &nodes[3], 1_000_000, temporary_channel_id); @@ -1686,30 +1614,15 @@ mod test { connect_blocks(&nodes[1], CHAN_CONFIRM_DEPTH - 1); confirm_transaction_at(&nodes[3], &tx, conf_height); connect_blocks(&nodes[3], CHAN_CONFIRM_DEPTH - 1); - let as_channel_ready = get_event_msg!( - nodes[1], - MessageSendEvent::SendChannelReady, - nodes[3].node.get_our_node_id() - ); - nodes[1].node.handle_channel_ready( - nodes[3].node.get_our_node_id(), - &get_event_msg!( - nodes[3], - MessageSendEvent::SendChannelReady, - nodes[1].node.get_our_node_id() - ), - ); - get_event_msg!( - nodes[1], - MessageSendEvent::SendChannelUpdate, - nodes[3].node.get_our_node_id() - ); - nodes[3].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &as_channel_ready); - get_event_msg!( - nodes[3], - MessageSendEvent::SendChannelUpdate, - nodes[1].node.get_our_node_id() - ); + + let bs_channel_ready = + get_event_msg!(nodes[1], MessageSendEvent::SendChannelReady, node_d_id); + let ds_channel_ready = + get_event_msg!(nodes[3], MessageSendEvent::SendChannelReady, node_b_id); + nodes[1].node.handle_channel_ready(node_d_id, &ds_channel_ready); + get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, node_d_id); + nodes[3].node.handle_channel_ready(nodes[1].node.get_our_node_id(), &bs_channel_ready); + get_event_msg!(nodes[3], MessageSendEvent::SendChannelUpdate, node_b_id); expect_channel_ready_event(&nodes[1], &nodes[3].node.get_our_node_id()); expect_channel_ready_event(&nodes[3], &nodes[1].node.get_our_node_id()); From 01f50bc3f57ee94a3d9009039c4d2e074e5d5f3e Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 1 May 2025 21:19:02 +0000 Subject: [PATCH 11/11] Run `rustfmt` on `inbound_payment.rs` --- lightning/src/ln/inbound_payment.rs | 200 ++++++++++++++++++++-------- rustfmt_excluded_files | 1 - 2 files changed, 141 insertions(+), 60 deletions(-) diff --git a/lightning/src/ln/inbound_payment.rs b/lightning/src/ln/inbound_payment.rs index 87781793d06..53b212428ca 100644 --- a/lightning/src/ln/inbound_payment.rs +++ b/lightning/src/ln/inbound_payment.rs @@ -9,18 +9,18 @@ //! Utilities to generate inbound payment information in service of invoice creation. -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::hashes::{Hash, HashEngine}; use crate::crypto::chacha20::ChaCha20; use crate::crypto::utils::hkdf_extract_expand_6x; use crate::ln::msgs; use crate::ln::msgs::MAX_VALUE_MSAT; -use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::offers::nonce::Nonce; use crate::sign::EntropySource; +use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::util::errors::APIError; use crate::util::logger::Logger; @@ -112,8 +112,12 @@ impl Method { match bits { bits if bits == Method::LdkPaymentHash as u8 => Ok(Method::LdkPaymentHash), bits if bits == Method::UserPaymentHash as u8 => Ok(Method::UserPaymentHash), - bits if bits == Method::LdkPaymentHashCustomFinalCltv as u8 => Ok(Method::LdkPaymentHashCustomFinalCltv), - bits if bits == Method::UserPaymentHashCustomFinalCltv as u8 => Ok(Method::UserPaymentHashCustomFinalCltv), + bits if bits == Method::LdkPaymentHashCustomFinalCltv as u8 => { + Ok(Method::LdkPaymentHashCustomFinalCltv) + }, + bits if bits == Method::UserPaymentHashCustomFinalCltv as u8 => { + Ok(Method::UserPaymentHashCustomFinalCltv) + }, bits if bits == Method::SpontaneousPayment as u8 => Ok(Method::SpontaneousPayment), unknown => Err(unknown), } @@ -139,16 +143,24 @@ fn min_final_cltv_expiry_delta_from_metadata(bytes: [u8; METADATA_LEN]) -> u16 { /// /// [phantom node payments]: crate::sign::PhantomKeysManager /// [`NodeSigner::get_inbound_payment_key`]: crate::sign::NodeSigner::get_inbound_payment_key -pub fn create(keys: &ExpandedKey, min_value_msat: Option, - invoice_expiry_delta_secs: u32, entropy_source: &ES, current_time: u64, - min_final_cltv_expiry_delta: Option) -> Result<(PaymentHash, PaymentSecret), ()> - where ES::Target: EntropySource +pub fn create( + keys: &ExpandedKey, min_value_msat: Option, invoice_expiry_delta_secs: u32, + entropy_source: &ES, current_time: u64, min_final_cltv_expiry_delta: Option, +) -> Result<(PaymentHash, PaymentSecret), ()> +where + ES::Target: EntropySource, { - let metadata_bytes = construct_metadata_bytes(min_value_msat, if min_final_cltv_expiry_delta.is_some() { + let metadata_bytes = construct_metadata_bytes( + min_value_msat, + if min_final_cltv_expiry_delta.is_some() { Method::LdkPaymentHashCustomFinalCltv } else { Method::LdkPaymentHash - }, invoice_expiry_delta_secs, current_time, min_final_cltv_expiry_delta)?; + }, + invoice_expiry_delta_secs, + current_time, + min_final_cltv_expiry_delta, + )?; let mut iv_bytes = [0 as u8; IV_LEN]; let rand_bytes = entropy_source.get_secure_random_bytes(); @@ -174,13 +186,21 @@ pub fn create(keys: &ExpandedKey, min_value_msat: Option, /// on versions of LDK prior to 0.0.114. /// /// [phantom node payments]: crate::sign::PhantomKeysManager -pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option, payment_hash: PaymentHash, - invoice_expiry_delta_secs: u32, current_time: u64, min_final_cltv_expiry_delta: Option) -> Result { - let metadata_bytes = construct_metadata_bytes(min_value_msat, if min_final_cltv_expiry_delta.is_some() { +pub fn create_from_hash( + keys: &ExpandedKey, min_value_msat: Option, payment_hash: PaymentHash, + invoice_expiry_delta_secs: u32, current_time: u64, min_final_cltv_expiry_delta: Option, +) -> Result { + let metadata_bytes = construct_metadata_bytes( + min_value_msat, + if min_final_cltv_expiry_delta.is_some() { Method::UserPaymentHashCustomFinalCltv } else { Method::UserPaymentHash - }, invoice_expiry_delta_secs, current_time, min_final_cltv_expiry_delta)?; + }, + invoice_expiry_delta_secs, + current_time, + min_final_cltv_expiry_delta, + )?; let mut hmac = HmacEngine::::new(&keys.user_pmt_hash_key); hmac.input(&metadata_bytes); @@ -196,11 +216,14 @@ pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option, payment #[cfg(async_payments)] pub(super) fn create_for_spontaneous_payment( keys: &ExpandedKey, min_value_msat: Option, invoice_expiry_delta_secs: u32, - current_time: u64, min_final_cltv_expiry_delta: Option + current_time: u64, min_final_cltv_expiry_delta: Option, ) -> Result { let metadata_bytes = construct_metadata_bytes( - min_value_msat, Method::SpontaneousPayment, invoice_expiry_delta_secs, current_time, - min_final_cltv_expiry_delta + min_value_msat, + Method::SpontaneousPayment, + invoice_expiry_delta_secs, + current_time, + min_final_cltv_expiry_delta, )?; let mut hmac = HmacEngine::::new(&keys.spontaneous_pmt_key); @@ -213,7 +236,9 @@ pub(super) fn create_for_spontaneous_payment( Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key)) } -pub(super) fn calculate_absolute_expiry(highest_seen_timestamp: u64, invoice_expiry_delta_secs: u32) -> u64 { +pub(super) fn calculate_absolute_expiry( + highest_seen_timestamp: u64, invoice_expiry_delta_secs: u32, +) -> u64 { // We assume that highest_seen_timestamp is pretty close to the current time - it's updated when // we receive a new block with the maximum time we've seen in a header. It should never be more // than two hours in the future. Thus, we add two hours here as a buffer to ensure we @@ -222,8 +247,10 @@ pub(super) fn calculate_absolute_expiry(highest_seen_timestamp: u64, invoice_exp highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200 } -fn construct_metadata_bytes(min_value_msat: Option, payment_type: Method, - invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64, min_final_cltv_expiry_delta: Option) -> Result<[u8; METADATA_LEN], ()> { +fn construct_metadata_bytes( + min_value_msat: Option, payment_type: Method, invoice_expiry_delta_secs: u32, + highest_seen_timestamp: u64, min_final_cltv_expiry_delta: Option, +) -> Result<[u8; METADATA_LEN], ()> { if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT { return Err(()); } @@ -234,18 +261,23 @@ fn construct_metadata_bytes(min_value_msat: Option, payment_type: Method, }; min_amt_msat_bytes[0] |= (payment_type as u8) << METHOD_TYPE_OFFSET; - let expiry_timestamp = calculate_absolute_expiry(highest_seen_timestamp, invoice_expiry_delta_secs); + let expiry_timestamp = + calculate_absolute_expiry(highest_seen_timestamp, invoice_expiry_delta_secs); let mut expiry_bytes = expiry_timestamp.to_be_bytes(); // `min_value_msat` should fit in (64 bits - 3 payment type bits =) 61 bits as an unsigned integer. // This should leave us with a maximum value greater than the 21M BTC supply cap anyway. - if min_value_msat.is_some() && min_value_msat.unwrap() > ((1u64 << 61) - 1) { return Err(()); } + if min_value_msat.is_some() && min_value_msat.unwrap() > ((1u64 << 61) - 1) { + return Err(()); + } // `expiry_timestamp` should fit in (64 bits - 2 delta bytes =) 48 bits as an unsigned integer. // Bitcoin's block header timestamps are actually `u32`s, so we're technically already limited to // the much smaller maximum timestamp of `u32::MAX` for now, but we check the u64 `expiry_timestamp` // for future-proofing. - if min_final_cltv_expiry_delta.is_some() && expiry_timestamp > ((1u64 << 48) - 1) { return Err(()); } + if min_final_cltv_expiry_delta.is_some() && expiry_timestamp > ((1u64 << 48) - 1) { + return Err(()); + } if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta { let bytes = min_final_cltv_expiry_delta.to_be_bytes(); @@ -261,13 +293,19 @@ fn construct_metadata_bytes(min_value_msat: Option, payment_type: Method, Ok(metadata_bytes) } -fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], metadata_key: &[u8; METADATA_KEY_LEN]) -> PaymentSecret { +fn construct_payment_secret( + iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], + metadata_key: &[u8; METADATA_KEY_LEN], +) -> PaymentSecret { let mut payment_secret_bytes: [u8; 32] = [0; 32]; let (iv_slice, encrypted_metadata_slice) = payment_secret_bytes.split_at_mut(IV_LEN); iv_slice.copy_from_slice(iv_bytes); ChaCha20::encrypt_single_block( - metadata_key, iv_bytes, encrypted_metadata_slice, metadata_bytes + metadata_key, + iv_bytes, + encrypted_metadata_slice, + metadata_bytes, ); PaymentSecret(payment_secret_bytes) } @@ -308,14 +346,17 @@ fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METAD /// [`NodeSigner::get_inbound_payment_key`]: crate::sign::NodeSigner::get_inbound_payment_key /// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment /// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash -pub(super) fn verify(payment_hash: PaymentHash, payment_data: &msgs::FinalOnionHopData, - highest_seen_timestamp: u64, keys: &ExpandedKey, logger: &L) -> Result< - (Option, Option), ()> - where L::Target: Logger +pub(super) fn verify( + payment_hash: PaymentHash, payment_data: &msgs::FinalOnionHopData, highest_seen_timestamp: u64, + keys: &ExpandedKey, logger: &L, +) -> Result<(Option, Option), ()> +where + L::Target: Logger, { let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_data.payment_secret, keys); - let payment_type_res = Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET); + let payment_type_res = + Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET); let mut amt_msat_bytes = [0; AMT_MSAT_LEN]; let mut expiry_bytes = [0; METADATA_LEN - AMT_MSAT_LEN]; amt_msat_bytes.copy_from_slice(&metadata_bytes[..AMT_MSAT_LEN]); @@ -332,42 +373,63 @@ pub(super) fn verify(payment_hash: PaymentHash, payment_data: &msgs::F let mut hmac = HmacEngine::::new(&keys.user_pmt_hash_key); hmac.input(&metadata_bytes[..]); hmac.input(&payment_hash.0); - if !fixed_time_eq(&iv_bytes, &Hmac::from_engine(hmac).to_byte_array().split_at_mut(IV_LEN).0) { - log_trace!(logger, "Failing HTLC with user-generated payment_hash {}: unexpected payment_secret", &payment_hash); - return Err(()) + if !fixed_time_eq( + &iv_bytes, + &Hmac::from_engine(hmac).to_byte_array().split_at_mut(IV_LEN).0, + ) { + log_trace!( + logger, + "Failing HTLC with user-generated payment_hash {}: unexpected payment_secret", + &payment_hash + ); + return Err(()); } }, Ok(Method::LdkPaymentHash) | Ok(Method::LdkPaymentHashCustomFinalCltv) => { match derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys) { Ok(preimage) => payment_preimage = Some(preimage), Err(bad_preimage_bytes) => { - log_trace!(logger, "Failing HTLC with payment_hash {} due to mismatching preimage {}", &payment_hash, log_bytes!(bad_preimage_bytes)); - return Err(()) - } + log_trace!( + logger, + "Failing HTLC with payment_hash {} due to mismatching preimage {}", + &payment_hash, + log_bytes!(bad_preimage_bytes) + ); + return Err(()); + }, } }, Ok(Method::SpontaneousPayment) => { let mut hmac = HmacEngine::::new(&keys.spontaneous_pmt_key); hmac.input(&metadata_bytes[..]); - if !fixed_time_eq(&iv_bytes, &Hmac::from_engine(hmac).to_byte_array().split_at_mut(IV_LEN).0) { + if !fixed_time_eq( + &iv_bytes, + &Hmac::from_engine(hmac).to_byte_array().split_at_mut(IV_LEN).0, + ) { log_trace!(logger, "Failing async payment HTLC with sender-generated payment_hash {}: unexpected payment_secret", &payment_hash); - return Err(()) + return Err(()); } }, Err(unknown_bits) => { - log_trace!(logger, "Failing HTLC with payment hash {} due to unknown payment type {}", &payment_hash, unknown_bits); + log_trace!( + logger, + "Failing HTLC with payment hash {} due to unknown payment type {}", + &payment_hash, + unknown_bits + ); return Err(()); - } + }, } match payment_type_res { Ok(Method::UserPaymentHashCustomFinalCltv) | Ok(Method::LdkPaymentHashCustomFinalCltv) => { - min_final_cltv_expiry_delta = Some(min_final_cltv_expiry_delta_from_metadata(metadata_bytes)); + min_final_cltv_expiry_delta = + Some(min_final_cltv_expiry_delta_from_metadata(metadata_bytes)); // Zero out first two bytes of expiry reserved for `min_final_cltv_expiry_delta`. expiry_bytes[0] &= 0; expiry_bytes[1] &= 0; - } - _ => {} + }, + _ => {}, } let min_amt_msat: u64 = u64::from_be_bytes(amt_msat_bytes.into()); @@ -375,45 +437,62 @@ pub(super) fn verify(payment_hash: PaymentHash, payment_data: &msgs::F if payment_data.total_msat < min_amt_msat { log_trace!(logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", &payment_hash, payment_data.total_msat, min_amt_msat); - return Err(()) + return Err(()); } if expiry < highest_seen_timestamp { log_trace!(logger, "Failing HTLC with payment_hash {}: expired payment", &payment_hash); - return Err(()) + return Err(()); } Ok((payment_preimage, min_final_cltv_expiry_delta)) } -pub(super) fn get_payment_preimage(payment_hash: PaymentHash, payment_secret: PaymentSecret, keys: &ExpandedKey) -> Result { +pub(super) fn get_payment_preimage( + payment_hash: PaymentHash, payment_secret: PaymentSecret, keys: &ExpandedKey, +) -> Result { let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_secret, keys); match Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET) { Ok(Method::LdkPaymentHash) | Ok(Method::LdkPaymentHashCustomFinalCltv) => { - derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys) - .map_err(|bad_preimage_bytes| APIError::APIMisuseError { - err: format!("Payment hash {} did not match decoded preimage {}", &payment_hash, log_bytes!(bad_preimage_bytes)) - }) + derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys).map_err( + |bad_preimage_bytes| APIError::APIMisuseError { + err: format!( + "Payment hash {} did not match decoded preimage {}", + &payment_hash, + log_bytes!(bad_preimage_bytes) + ), + }, + ) + }, + Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => { + Err(APIError::APIMisuseError { + err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash" + .to_string(), + }) }, - Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => Err(APIError::APIMisuseError { - err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string() - }), Ok(Method::SpontaneousPayment) => Err(APIError::APIMisuseError { - err: "Can't extract payment preimage for spontaneous payments".to_string() + err: "Can't extract payment preimage for spontaneous payments".to_string(), }), - Err(other) => Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }), + Err(other) => { + Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }) + }, } } -fn decrypt_metadata(payment_secret: PaymentSecret, keys: &ExpandedKey) -> ([u8; IV_LEN], [u8; METADATA_LEN]) { +fn decrypt_metadata( + payment_secret: PaymentSecret, keys: &ExpandedKey, +) -> ([u8; IV_LEN], [u8; METADATA_LEN]) { let mut iv_bytes = [0; IV_LEN]; let (iv_slice, encrypted_metadata_bytes) = payment_secret.0.split_at(IV_LEN); iv_bytes.copy_from_slice(iv_slice); let mut metadata_bytes: [u8; METADATA_LEN] = [0; METADATA_LEN]; ChaCha20::encrypt_single_block( - &keys.metadata_key, &iv_bytes, &mut metadata_bytes, encrypted_metadata_bytes + &keys.metadata_key, + &iv_bytes, + &mut metadata_bytes, + encrypted_metadata_bytes, ); (iv_bytes, metadata_bytes) @@ -421,7 +500,10 @@ fn decrypt_metadata(payment_secret: PaymentSecret, keys: &ExpandedKey) -> ([u8; // Errors if the payment preimage doesn't match `payment_hash`. Returns the bad preimage bytes in // this case. -fn derive_ldk_payment_preimage(payment_hash: PaymentHash, iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], keys: &ExpandedKey) -> Result { +fn derive_ldk_payment_preimage( + payment_hash: PaymentHash, iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], + keys: &ExpandedKey, +) -> Result { let mut hmac = HmacEngine::::new(&keys.ldk_pmt_hash_key); hmac.input(iv_bytes); hmac.input(metadata_bytes); @@ -429,5 +511,5 @@ fn derive_ldk_payment_preimage(payment_hash: PaymentHash, iv_bytes: &[u8; IV_LEN if !fixed_time_eq(&payment_hash.0, &Sha256::hash(&decoded_payment_preimage).to_byte_array()) { return Err(decoded_payment_preimage); } - return Ok(PaymentPreimage(decoded_payment_preimage)) + return Ok(PaymentPreimage(decoded_payment_preimage)); } diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 7f920c51b77..fceda5042f0 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -16,7 +16,6 @@ lightning/src/ln/channel.rs lightning/src/ln/channelmanager.rs lightning/src/ln/functional_test_utils.rs lightning/src/ln/functional_tests.rs -lightning/src/ln/inbound_payment.rs lightning/src/ln/max_payment_path_len_tests.rs lightning/src/ln/mod.rs lightning/src/ln/monitor_tests.rs